对于EntityA与EntityB具有多对一关系的核心数据模型,我想创建一个EntityA对象列表,按照与它们相关的EntityB的名称进行排序。通常要这样做,我会设置这样的获取请求:
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
然后我会设置我的请求值:(在这种情况下,它是按物种名称排序的植物列表。某些植物没有物种设置。)
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Plant" inManagedObjectContext:self.managedObjectContext];
NSSortDescriptor *sortDescriptorOne = [[NSSortDescriptor alloc] initWithKey:@"species.name" ascending:YES];
NSString *sectionKeyPath = @"species.name";
然后我用通常的东西完成它:
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
NSArray *sortDescriptors = @[sortDescriptorOne];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:sectionKeyPath
cacheName:@"plantsCache"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[NSFetchedResultsController deleteCacheWithName:@"plantsCache"];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
但我得到的结果对我不起作用,因为这种关系是可选的。因此,某些EntityA与EntityB有关系,有些则没有。当EntityA的关系值为零时,结果控制器似乎不知道该怎么做。
我可以做些什么建议继续使用关系的值创建部分,但允许某些对象为nil?
答案 0 :(得分:3)
在Plant
中设置瞬态属性,如下所示:
-(NSString*)speciesName {
return self.species ? self.species.name : @"";
}
您现在可以使用speciesName
作为sectionNameKeyPath
。
答案 1 :(得分:0)
使用Swift 3.0进入此阶段。有两个实体EntityA和EntityB,其中EntityA通常属于(有一个指针)某个EntityB,但也可能是无主的。
Swift修复是为EntityA添加一个扩展,如果检测到nil条件,则返回一个空字符串。
extension Note {
var bookTitleOrNil : String {
if let bookTitle = self.book?.title {
return bookTitle
}
return ""
}
}
然后在构建fetchRequestController(FRC)时替换以下内容:
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataManager.managedObjectContext, sectionNameKeyPath: "book.title", cacheName: nil)
使用sectionNameKeyPath的新扩展名:
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataManager.managedObjectContext, sectionNameKeyPath: "bookTitleOrNil", cacheName: nil)
然后,在为不同部分生成标题时,我使用了以下内容:
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let useIndexPath = IndexPath(row: 0, section: section) // Get first item in section (all notes in a section point to same book)
let note = frc.object(at: useIndexPath)
if let bookTitle = note.book?.title {
return bookTitle
} else {
return "Unlinked"
}
}
所以这些笔记首先按照它们所属的书排序,如章节标题所示(尽管不属于任何书籍的笔记首先在“未链接”标题下排序)。
此外,在FRC的fetchRequest中设置排序时,需要设置主排序描述符以使用book.title,然后使用任何其他排序,例如注释的标题。
let sortDescriptor1 = NSSortDescriptor(key: "book.title", ascending: true)
let sortDescriptor2 = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor1, sortDescriptor2]
当然,人们还可以设计应用程序,以便在创建笔记时通过额外检查将笔记始终属于书籍,并以此方式避免使用零件。