在视图控制器的dealloc NSManagedObjectContext添加场景时出错,但编辑场景确定

时间:2013-04-22 13:39:50

标签: core-data automatic-ref-counting nsmanagedobjectcontext

我有两个控制器,一个叫做AddressesController

@interface AddressesController : UITableViewController<ManageAddressDelegate>
@property(nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@end

通常由NSFetchedResultsController显示地址,并执行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中的地址为子控制器准备segue,该地址在AddressesController#prepareForSegue:sender中命名为editContext (也设置委托协议)

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;
}

在addContext中准备一个新地址以便添加:

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 ok之后将其保存到CoreData中。 我使用Magical Record来执行与CoreData相关的操作 以上代码 [address.managedObjectContext saveToPersistentStoreAndWait];“也会导致默认上下文被保存。 而我试图使用普通[NSManagedObjectContext:save:error],错误是一样的。

问题是,虽然添加和编辑逻辑相同的是99%,但它可以编辑。 当我添加一个地址时,它将保存到db,并在调用 [self.navigationController popViewControllerAnimated:YES] 时引发异常,当EditAddressController取消分配ivar 上下文时发生错误

EXC_BAD_ACCESS(代码= 2,地址= 0x3)

错误堆栈附带(仅列出一些关键功能):

[NSPersistStoreCache decrementRefCountForObjectID]
... 
[NSManagedObjectContext(_NestedContextSupport) managedContextDidUnregisterObjectsWithIDs:]
...
[NSManagedObjectContext dealloc]

1 个答案:

答案 0 :(得分:0)

经过几轮测试,我找到了根本原因:

我们应该在以下消息之后向托管对象上下文发送重置消息:

[address.managedObjectContext saveToPersistentStoreAndWait];

[address.managedObjectContext reset];

我不知道为什么编辑对象不会导致错误。