在兔子洞的下方,我走了。我现在已经成功保存了我的孩子moc: Core Data Parent/Child context save fail
我的下一个障碍是我的主要上下文无法使用子结果进行更新。基本上我有200个条目的tableview现在是空白的。
以下是我的设置:(包含上一篇文章中的所有代码)
在我的app委托中,我使用NSMainQueueConcurrencyType设置主要的managedobjectcontext:
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];//[[NSManagedObjectContext alloc] init];
//_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
当我的数据调用返回json时,我设置了子moc并按照以下方式进行工作:
- (void)APIManager:(APIManager *)manager didGetContactsWithInfo:(NSDictionary *)info
{
NSManagedObjectContext *mainMOC = self.managedObjectContext;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[moc setParentContext:mainMOC];
[moc setUndoManager:nil];
BCRAccount *account2 = (BCRAccount*)[moc objectWithID:[self.loggedInAccount objectID]];
[moc performBlock:^{
//do all work on child moc
//within block there is a core data relationship reference:
[contact addAccountsObject:account2];
[self saveMOC:moc completion:^(NSError *error) {
// Completion handler is called from main-thread, after save has finished
if (error) {
// Handle error
NSLog(@"save error %@", error);
} else {
NSLog(@"save success");
}
}];
}];
saveMOC方法:
- (void)saveMOC:(NSManagedObjectContext*)moc
completion:(void(^)(NSError *error))completion {
[moc performBlock:^{
NSError *error = nil;
if ([moc save:&error]) {
if (moc.parentContext) {
return [self saveMOC:moc.parentContext completion:completion];
}
}
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(error);
}
}];
}
好的,这是保存,直到我重新启用“帐户”实体和“联系”实体之间的关系。
帐户实体与目的地为“联系人”的关系为“联系人”,反之为“帐户”。删除规则为“Nullify”,类型为“To many”。
联系人实体的关系为“帐户”,目的地为“帐户”,反向设置为“联系人”。删除规则为“Nullify”,类型为“To many”。
这种关系导致的moc错误是:
错误域= NSCocoaErrorDomain代码= 1550“联系人无效。” UserInfo = {悬挂对无效对象的引用。= null,NSValidationErrorValue =托管对象上的关系'联系人'
我认为此错误是问题的根源,但对于上下文,以下是视图控制器中使用的NSFetchedResultsController,它显示联系人的表视图:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[BCRContact entityName] inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSArray *sortDescriptors =
@[[NSSortDescriptor sortDescriptorWithKey:@"isNewContact" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:@"status" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"fullName" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"company" ascending:YES]];
[fetchRequest setSortDescriptors:sortDescriptors];
fetchRequest.predicate = [self predicateWithSearchString:nil];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
//NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
该表在此处生成单元格:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
ContactListCell *cell = (ContactListCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ContactListCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
BCRContact *contact = [self.fetchedResultsController objectAtIndexPath:indexPath];
//update cell
}
好的,这是粗略的设置。当tableview只是一个上下文时,tableview会很好。所以,问题是如何在tableview中正确反映孩子的moc数据。
如果我能提供更多细节,请告诉我。
答案 0 :(得分:1)
破解了!在performBlock之前我需要通过带有objectWithID的moc建立帐户实体。 BCRAccount account2 =(BCRAccount)[moc objectWithID:[self.loggedInAccount objectID]];之后关系工作:[联系addAccountsObject:account2];