CoreData 并发
Posted
技术标签:
【中文标题】CoreData 并发【英文标题】:CoreData concurrency 【发布时间】:2014-06-11 19:38:13 【问题描述】:我遇到了 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】:在您的第一个代码块中,您希望这样做:
- (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 属性中。以上是关于CoreData 并发的主要内容,如果未能解决你的问题,请参考以下文章