错误而用于添加场景的视图控制器的dealloc的NSManagedObjectContext,但确定为编辑场景
我已经两个控制器,一个被NSFetchedResultsController错误而用于添加场景的视图控制器的dealloc的NSManagedObjectContext,但确定为编辑场景
@interface AddressesController : UITableViewController<ManageAddressDelegate>
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@end
哪个显示地址通常称作AddressesController,并执行SegueAddAddress为用户动作如:
- (IBAction)addButtonClicked:(id)sender {
[self performSegueWithIdentifier:SegueNewAddress sender:sender];
}
,并执行SegueEditAddress当单击某行:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
Address *address = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self performSegueWithIdentifier:SegueEditAddress sender:address];
}
另一个控制器EditAddressController,它的两个SegueAddAddress和SegueEditAddress的destinationViewController:
@interface EditAddressController : UITableViewController<EZFormDelegate>
@property (strong, nonatomic) Address *address;
@property (strong, nonatomic) NSManagedObjectContext *context;
@property (weak, nonatomic) id <ManageAddressDelegate> delegate;
@end
我将与子的NSManagedObjectContext命名为编辑上下文中AddressesController#prepareForSegue的地址准备子控制器SEGUE:发件人 (设置代表协议也)
if ([segue.identifier isEqualToString:SegueEditAddress]) {
EditAddressController *controller = segue.destinationViewController;
controller.delegate = self;
NSManagedObjectContext *editContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
editContext.MR_workingName = @"Edit Address Context";
[editContext setParentContext:[self.fetchedResultsController managedObjectContext]];
Address *address = sender;
Address *editAddress = [address inContext:editContext];
controller.address = editAddress;
controller.context = editContext;
}
为还加入准备在addingContext一个新地址:
if ([segue.identifier isEqualToString:SegueNewAddress]) {
EditAddressController *controller = segue.destinationViewController;
controller.delegate = self;
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
addingContext.MR_workingName = @"Adding Address Context";
[addingContext setParentContext:[self.fetchedResultsController managedObjectContext]];
Address *newAddress = [Address createInContext:addingContext];
controller.address = newAddress;
controller.context = addingContext;
}
当用户单击保存EditAddressController按钮,它会回调委托(AddressesController)与下面的代码后,填写地址属性:
- (IBAction)save:(id)sender {
[self.delegate controller:self save:self.address];
}
和原点AddressesController将由相同的处理新的或编辑行动回调函数:
- (void)controller:(EditAddressController *)controller save:(Address *)address {
NSArray *keys = @[@"username", @"phone", @"zipcode", @"street"];
NSDictionary *attributes = [address dictionaryWithValuesForKeys:keys];
void (^success)(AFHTTPRequestOperation *, id) = ^(AFHTTPRequestOperation *operation, id responseObject) {
[address importValuesForKeysWithObject:[responseObject JSONValue]];
[address.managedObjectContext saveToPersistentStoreAndWait];
[self.navigationController popViewControllerAnimated:YES];
};
void (^failure)(AFHTTPRequestOperation *, NSError *) = ^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(@"Failed to create address because of: %@", error);
};
if (address.id == nil || address.id.intValue == 0) {
[self.http postPath:@"addresses" parameters:parameters success:success failure:failure];
} else {
NSString *path = [NSString stringWithFormat:@"addresses/%@", address.id];
[self.http putPath:path parameters:parameters success:success failure:failure];
}
}
该函数只是将新的或编辑的地址发布到服务器,并在http确定后将其保存到CoreData中。 我使用魔法记录来执行CoreData相关操作 和上述代码[address.managedObjectContext saveToPersistentStoreAndWait];”意愿引起默认上下文中也被保存 和我曾尝试使用正常[的NSManagedObjectContext:保存:错误]中,错误是一样的
问题是,虽然添加和编辑逻辑是相同的99%,但它可以编辑。 当我添加一个地址,它将被保存到数据库,并引发一个异常当[self。navigationController popViewControllerAnimated:YES]被调用时,发生错误时EditAddressController的dealloc所述的ivar 上下文:
EXC_BAD_ACCESS(代码= 2,地址= 0x3)
错误堆栈带有(列出一些关键功能只):
[NSPersistStoreCache decrementRefCountForObjectID]
...
[NSManagedObjectContext(_NestedContextSupport) managedContextDidUnregisterObjectsWithIDs:]
...
[NSManagedObjectContext dealloc]
经过几轮测试中,我找到了根本原因:
我们应该低于消息后发送一个复位消息给管理对象上下文:
[address.managedObjectContext saveToPersistentStoreAndWait];
[address.managedObjectContext reset];
而且我不知道为什么编辑对象不会造成错误的想法。
经过一些测试后,我发现两个案例之间最重要的区别是地址对象,新地址相关联的上下文似乎已经'绑定'并拒绝任何'release/dealloc'尝试。 – Kadvin 2013-04-23 06:11:02