这是我对Core Data的第一次尝试,所以我希望得到你的指导。
我的示例项目非常简单,我想创建一个显示人员列表的iOS应用程序。我正在寻找的是将同一家庭的所有成员聚集在一起。列表中的某些人不属于“家庭”。因此,UITableView
将是组和行的混合。
这里我在上下文中添加数据
Family *newFamily = [NSEntityDescription insertNewObjectForEntityForName:@“Family” inManagedObjectContext:self.managedObjectContext];
[newFamily setSurname:[dict objectForKey:@“surname”]];
NSMutableSet *members = [newTeam mutableSetValueForKey:@"members"];
for (NSDictionary *member in [dict objectForKey:@"members"]) {
Member *newMember = [NSEntityDescription insertNewObjectForEntityForName:@"Member" inManagedObjectContext:self.managedObjectContext];
[newMember setFirstName:[member objectForKey:@"firstName"]];
[newMember setAge:[member objectForKey:@“age”]];
[members addObject:newMember];
}
//Save context ...
在UITableViewController
中,我能够阅读并显示家庭/群组的名称。我很困惑你如何显示一个部分的所有对象。
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Family" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"surname" ascending:NO];
[fetchRequest setSortDescriptors:@[sortDescriptor]];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"surname" cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
return _fetchedResultsController;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// I DON'T KNOW WHAT TO DO HERE ...
// return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo name];
}
答案 0 :(得分:1)
首先,您需要修改模型以包含从Member
到Family
的反向关系,这可能是“to-one”。说出那个关系“家庭”。 (在这种情况下需要这种反向关系,见下文,但无论您是否认为需要它们,您几乎总是应该包含所有关系的反转。)
接下来,按如下方式修改FRC配置:底层实体应为Member
,因为tableView的每一行都代表一个Member
对象。 sectionNameKeyPath
应该是“family.surname”,因此FRC将根据相关Member
对象的surname
属性自动将Family
个对象放入部分。重要的是FRC的排序顺序与部分匹配(即同一部分中的所有Member
个对象必须一起排序),因此修改排序描述符以使用family.surname
(那么你可以如果需要,按firstName
排序:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Member" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *surnameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"family.surname" ascending:NO];
NSSortDescriptor *firstNameSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:NO];
[fetchRequest setSortDescriptors:@[surnameSortDescriptor, firstNameSortDescriptor]];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"family.surname" cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
return _fetchedResultsController;
}
最后,还有用于将FRC链接到tableView的样板代码(请参阅Apple Docs here)。你缺少的是:
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
if ([[self.fetchedResultsController sections] count] > 0) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
} else
return 0;
}
您的configureCell
方法同样需要确定要使用
Member
对象
Member *currentMember = [self.fetchedResultsController objectAtIndexPath:indexPath];
请注意,如果Member
内有Family
个对象,则FRC会记录一条警告消息,因为sectionName
将为零。但它会将所有这些组合在一起 - 您可能希望修改titleForHeaderInSection
以使用该部分的其他名称。
另请注意,FRC的部分是通过检查每个family.surname
对象的Member
来确定的。如果Family
个对象没有members
,那么Family
个对象将不会出现在表格视图中(即没有空白部分)。