CoreData并发

时间:2014-06-11 19:38:14

标签: ios core-data magicalrecord

我遇到CoreData持久性问题(MagicalRecord 2.2,iOS 7.x) 可以在任何线程上创建和使用主对象:

- (Collection *)collection {

    if (!_collection) {
        [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
            _collection = [Collection MR_createInContext:localContext];
            _collection.creationDate = [NSDate date];
            _collection.collectionDescription = @"";
            _collection.name = [CollectionHelper getNameForUnnamedCollection];
        }];
    }

    return _collection;
}

在任何代码处,我都可以开始在后台线程中为这个集合添加资源:

    if (self.photoSavingBlocksCount == 0) {
        [self beginPhotoSaving];
    }
    self.photoSavingBlocksCount++;
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    Collection *localCollection = [self.collection MR_inContext:localContext];
    [localCollection addNewResourceForImage:image thumb:thumb gallery:gallery type:RESOURCE_TYPE_IMAGE];
} completion:^(BOOL success, NSError *error) {
    self.photoSavingBlocksCount--;
    if (self.photoSavingBlocksCount == 0) {
        [self endPhotoSaving];
    }
}];

此代码标记上传到服务器的集合及其资源:

- (BOOL)markCollectionAsUploaded:(Collection *)collection {
    [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
        Collection *localCollection = [collection MR_inContext:localContext];
        localCollection.uploaded = @YES;
        localCollection.uploadDate = [NSDate date];
    }];
    return YES;
}

此代码工作正常,但如果我在此之前编辑集合,则此代码将失败并且集合不会保存为已上载! 换句话说,在下一次获取时,我将获得collection.uploaded == @NO!

此代码保存已编辑的集合

    [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {

            Collection *localCollection = [self.collection MR_inContext:localContext];

            NSSet *set = [NSSet setWithArray:self.deletedResources];

            localCollection.uploaded = @NO;
            localCollection.name = ([fieldName.text length] == 0 || [[fieldName.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0)
            ? [CollectionHelper getNameForUnnamedCollection]
            : fieldName.text;
            localCollection.collectionDescription = [fieldDescription.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

            for (Resource *resource in set) {
                Resource *localResource = [resource MR_inContext:localContext];
                [CollectionHelper removeResourceFiles:resource];
                [localResource MR_deleteEntity];
            }
        }];

在日志中,我看到每个上下文保存的相同图片:

-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x196e2ee0) → Saving <NSManagedObjectContext (0x196e2ee0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x196e2ee0) → Save Parents? 1
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x196e2ee0) → Save Synchronously? 1
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x17d83e30) → Saving <NSManagedObjectContext (0x17d83e30): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x17d83e30) → Save Parents? 1
-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x17d83e30) → Save Synchronously? 1

有人可以告诉我一个管理CoreData对象的正确方法吗?我将不胜感激。

1 个答案:

答案 0 :(得分:0)

在您的第一个代码块中,您希望这样做:

- (Collection *)collection {

    if (!_collection) {
        [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
            _collection = [Collection MR_createInContext:localContext];
            _collection.creationDate = [NSDate date];
            _collection.collectionDescription = @"";
            _collection.name = [CollectionHelper getNameForUnnamedCollection];
        }];
    }
    _collection = [_collection MR_inContext:self.context];
    return _collection;
}

从保存块返回时,localContext将从内存中丢弃,您的对象将无法保存。为避免此问题,您应该将此新对象刷新到本地更长寿的上下文中。您可以通过不使用块并直接保存到更长寿的上下文中来完全避免这种模式。

老实说,我没有阅读剩下的问题,因为这应该首先清理,以避免晦涩的崩溃......