在表格视图部分中对核心数据对象进行排序

Posted

技术标签:

【中文标题】在表格视图部分中对核心数据对象进行排序【英文标题】:Ordering core data objects inside a table view section 【发布时间】:2014-01-28 18:57:01 【问题描述】:

我正在使用 NSSortDescriptors 对核心数据对象进行排序并根据日期属性创建表格视图部分。使用这种 SortDescriptor,表格视图部分按预期排序,但部分内的行也按相同的日期属性排序。有没有办法在每个部分内有另一个订购系统?我猜主要问题是核心数据存储日期对象的日期+时间值,这样就没有对象具有完全相同的日期值。但我需要根据另一个属性对同一部分内的对象进行排序。 谢谢。

这是我的 NSFetchedResultsController 代码:

-(NSFetchedResultsController*)fetchedResultsController

    if (_fetchedResultsController != nil)
        return _fetchedResultsController;
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
    NSManagedObjectContext *context = self.managedObjectContext;
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:context];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"itemDate" ascending:YES];
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc]initWithKey:@"itemName" ascending:NO];

    NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor,sortDescriptor1, nil];
    fetchRequest.sortDescriptors = sortDescriptors;
    _fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"sectionIdentifier" cacheName:nil];
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;

编辑问题

这是添加到 cellForRowAtIndexPath 方法中的一段代码:

int indexpathsection = indexPath.section;
    [self sortedSectionForIndex:indexpathsection];
    NSLog(@"INDEXPATH= %ld", (long)indexPath.section);

这是马库斯提出的方法:

- (NSArray*)sortedSectionForIndex:(NSInteger)index

    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"priority" ascending:YES];
    id section = [[self fetchedResultsController] sections][index];
    NSLog(@"INDEX********* = %ld", (long)index);
    NSArray *objects = [section objects];
    NSArray *sorted = [objects sortedArrayUsingDescriptors:@[sort]];
    return sorted;

【问题讨论】:

欢迎来到***!如果你展示你的数据结构/代码,你会得到更好的答案。 谢谢,我会将我的 NSFetchedResultsController 代码添加到我的问题中。 @CorleyBrigman,我已将代码添加到问题中。 【参考方案1】:

NSFetchedResultsController 用于通过单个排序或一组排序来控制排序顺序。它不是为了做你想做的事。

但你可以做到,只是不够干净。

首先,讨论对一个部分进行排序。这不需要您编写自己的排序算法:

- (NSArray*)sortedSectionForIndex:(NSInteger)index

    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"MyKey" ascending:YES];
    id section = [[self fetchedResultsController] sections][index];
    NSArray *objects = [section objects];
    NSArray *sorted = [objects sortedArrayUsingDescriptors:@[sort]];
    return sorted

使用该方法,您可以在想要检索对象时要求对部分进行排序。但是,这是低效的,因为每次您想要触摸 UITableViewController 中的 LOT 的对象时都会进行排序。

取而代之的是,将这个示例与您的 NSFetchedResultsController 及其委托方法集成,以便您存储排序后的数组并保持它们同步。这样,您只需在数据更改时进行排序,而不是在每次方法调用时进行排序。

更新

我提供给您的排序代码不会对NSFetchedResultsController 内部 的内容进行排序。它获取该部分中的内容,对其进行排序并返回排序后的数组。所以你需要使用它返回的内容:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    NSArray *sorted = [self sortedSectionForIndex:[indexPath section]];
    id object = [sorted objectAtIndex:[indexPath row]];

    id cell = ...; //Now get your cell reference

    //Now update your cell with the data from object

    return cell;

【讨论】:

我认为您的回答应该对我有所帮助,但在哪里整合它将是我的下一个问题。你说要将它与我的 NSFetchedResultsController 及其委托方法集成,但是如何,我知道这是一个返回数组的完整方法,但我不知道我应该从哪里调用它......谢谢你的帮助 从任何需要访问数据的地方。 -cellForRowAtIndexPath... 可能是一个不错的起点。 Marcus,当从 cellForRowAtIndexPath 方法调用你的方法时,我想我应该这样做:[self sortedSectionForIndex:sectionIndex]; sectionIndex 应该是要排序的部分。 马库斯,我做了如下: int indexPathSection = indexPath.section; [self sortedSectionForIndex:indexPathSection];在 cellForRowAtIndexPath 方法内部。它不会对放在 sortDescriptorWithkey 中的属性进行排序。 马库斯,你能帮我解决我之前的评论吗?我真的很感激。谢谢。【参考方案2】:

您可以在NSManagedObjectawakeFromFetch 方法中规范化属性的时间组件。

- (void) awakeFromFetch 
    [super awakeFromFetch];
    NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit  fromDate:self.itemDate];
    self.itemDate = [[NSCalendar currentCalendar] dateFromComponents:comps];     

此外,查看您的代码,您必须告诉NSFetchedResultsController 它应该基于什么分节符。为此,您可以在初始化时为分节符提供一个 keyPath。对于您的情况,不要使用sectionNameKeyPath:@"sectionIdentifier",而是使用第一个排序键:

    _fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"itemDate" cacheName:nil];

【讨论】:

谢谢,但是按照您的建议更改 sectionNameKeyPath 不起作用,这些部分未显示... 我添加了有关如何在托管对象中标准化 itemDate 的时间分量的信息。

以上是关于在表格视图部分中对核心数据对象进行排序的主要内容,如果未能解决你的问题,请参考以下文章

核心数据按格式化日期排序表格视图

Swift UITableView(无部分)过滤到带有部分的表格视图

如何对两个不同的核心数据对象进行排序?

是否可以在文本视图中对数据进行排序?

从 JSON 数据中对 UItableview 中的排序和部分进行排序

在 tableview 中对动态部分进行排序 |迅速