【问题标题】:CoreData concurrencyCoreData 并发
【发布时间】:2023-03-20 21:35:01
【问题描述】:

我遇到了 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 对象的方法吗?我将不胜感激。

【问题讨论】:

    标签: ios core-data magicalrecord


    【解决方案1】:

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

    - (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 从内存中被丢弃,您的对象将无法保存。为避免此问题,您应该将这个新对象刷新到本地、寿命更长的上下文中。您可以完全避免这种模式,方法是不使用块并直接保存到更长寿的上下文中。

    而且,老实说,我没有阅读问题的其余部分,因为应该首先澄清这一点,以避免出现晦涩的崩溃......

    【讨论】:

    • 感谢您的回答。我不明白你在 self.context 中提到了哪个上下文?
    • @NeverBe 如果您想在应用程序代码中的任何位置从 - (Collection *)collection 方法获取数据,则需要持久化上下文。这就是为什么您需要将上下文存储在 self.context 属性中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多