NSFetchedResultsController节使用显示顺序sorting

我目前有一个选项,允许用户更改我的iPhone应用程序中的类别的显示顺序。

我想使用NSFetchedResultsController部分表视图,以便部分标题是“category.displayOrder”sorting的“category.name”,其中“category”与我正在提取的实体具有TO-ONE关系。 我可以正确使用部分的唯一方法是使用“category.displayOrder”作为部分标题。

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"category.displayOrder" ascending:YES]; NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; [fetchRequest setFetchBatchSize:10]; NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"category.name" cacheName:nil]; 

任何想法如何我可以命名不同的部分标题,然后我sorting的属性?

不知道我是否完全理解你的问题,但我在我的应用程序中做了类似的事情,下面是我如何使其工作:

首先,fetchedResultsController方法,其中我根据我正在尝试做什么来设置sorting描述和谓词。 在这种情况下,我想按发行date按名称对电影标题进行sorting。 然后用我的谓词,我抓住一个特定的“types”,并在一定的“releaseDate”范围内的实体。

在我的fetchresultscontroller定义中,您将sectionNameKeyPath设置为“releaseDate”,所以我的部分标题将基于date。

 - (NSFetchedResultsController *)fetchedResultsController { if (fetchedResultsController_ != nil) { return fetchedResultsController_; } NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSSortDescriptor *sortByReleaseDate = [[NSSortDescriptor alloc] initWithKey:@"releaseDate" ascending:NO]; NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByReleaseDate,sortByName, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; [sortDescriptors release]; [sortByName release]; [sortByReleaseDate release]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(type == 'Movies') AND (releaseDate <= %@) AND (releaseDate >= %@)", [NSDate date], [NSDate dateWithTimeIntervalSinceNow:kOneDayTimeInterval*-30]]; [fetchRequest setPredicate:predicate]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Movie" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"releaseDate" cacheName:nil]; ...// Perform and return fetch here, error handling etc... return fetchedResultsController_; } 

然后在我的表中查看数据源委托方法,我将NSDate转换为NSString后返回每个头的实际标题(请记住,您必须返回NSString为一个tableview标题标题。

 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { NSString *rawDateStr = [[[self.fetchedResultsController sections] objectAtIndex:section] name]; //convert default date string to NSDate... NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZ"]; NSDate *date = [formatter dateFromString:rawDateStr]; //convert NSDate to format we want... [formatter setDateFormat:@"d MMMM yyyy"]; NSString *formattedDateStr = [formatter stringFromDate:date]; return formattedDateStr; } 

所以如果我想改变我的数据被显示为由titleName组织的方式,我会改变我的fetchedResultsController对象为:

 NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"titleName" cacheName:nil]; 

并修改我的tableview:titleForHeaderInSection:数据源方法来简单地返回titleName(已经是一个string):

  - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; } 

我希望这可以帮助你find解决你的具体问题。

欢呼声,Rog

我有同样的问题,我有另一种解决scheme – 使用sectionNameKeyPath即category.sectionName的瞬态属性。 看来,如果你使用核心数据属性作为sectionNameKeyPath它将尝试和sorting。

所以使用上面的例子:

 NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"category.displayOrder" ascending:YES]; NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"category.sectionName" cacheName:nil]; 

Category.h:

 @interface Category : NSManagedObject @property (nonatomic, retain) NSString* name; @property (nonatomic, retain) NSNumber* displayOrder; -(NSString*) sectionName; @end 

Category.m:

 @implementation Category @dynamic name; @dynamic displayOrder; -(NSString*) sectionName{ return self.name; } @end 

然后在你的视图控制器中:

 - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ id<NSFetchedResultsSectionInfo> sectionInfo=[self.resultsController.sections objectAtIndex:section]; return sectionInfo.name; } 

感谢Rog,我能够解决这个问题,并提出一个解决scheme。 这不是我想要的那么干净,所以如果有人有更好的方法,我很想听听它。

基于我所学到的(我可能是错的,请告诉我)您只能通过您订购表的属性来命名部分(sectionNameKeyPath)。 在我的情况下,我想使用名为displayOrder的属性对我的表进行sorting,但我不希望我的部分标题为0,1,2等。相反,我希望部分标题使用标题属性“Name1”对应于displayOrder的“Name2”等。 为此,我根据titleForHeaderInSection中的displayOrder确定标题标题:

  NSString *displayOrder = [sectionInfo name]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"Platform" inManagedObjectContext:managedObjectContext]]; NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setNumberStyle:NSNumberFormatterNoStyle]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"displayOrder == %@", [numberFormatter numberFromString:displayOrder]]; [fetchRequest setPredicate:predicate]; Platform *platform; NSError *error = nil; NSArray *fetchResults = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; if ([fetchResults count] > 0) { platform = [fetchResults objectAtIndex:0]; headerView.titleLabel.text = [platform name]; } else { headerView.titleLabel.text = @"Unknown"; } [numberFormatter release]; [fetchRequest release]; 

感谢Rog!

在我的情况下,我不得不RTFM:

- initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName:

如果该sectionNameKeyPathfetchRequest第一个sorting描述符指定的不同,它们必须生成相同的相关sorting 。 例如,fetchRequest中的第一个sorting描述符可以指定持久属性的关键字; sectionNameKeyPath可以为从持久性属性派生的瞬态属性指定一个键。

当被pipe理对象的sectionNameKeyPathNSSortDescriptor属性更改为不同于其他属性的sorting顺序时,会在表视图sorting中产生不一致。

资源:
https://richardwarrender.com/2010/10/core-data-objects-in-wrong-sections/