在iPhone的核心数据中,我遇到了各种错误,试图将数据保存到NSManagedObjectContext.
我相信我的问题与我使用NSManagedObjectContext多线程中使用的问题有关.
所以我想创建一个新的NSManagedObjectContext并尝试,但我找不到简单创建新实例的示例代码...
我知道这很简单,但我真的很感激这里的任何帮助.
注意,我在Apple文档上看过这篇文章:http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/CoreDataUtilityTutorial/Articles/05_createStack.html
但是这使用了一些我不熟悉的代码,比如iPhone上不支持的XMLStore等.
在我的应用程序中,我有一个"主" NSPrivateQueueConcurrencyType上下文,它充当NSMainQueueConcurrencyType视图控制器依赖和传递的上下文的父级.我想这样做是为了利用异步保存(这个应用程序使用iCloud与核心数据,并节省了很多工作导出无处不在的日志).该设置类似于本文底部提到的Zarra方法
在应用程序中保存通常如下所示:
[context save:nil];
[context.parentContext performBlock:^{
[context.parentContext save:nil];
}];
Run Code Online (Sandbox Code Playgroud)
这似乎适用于小编辑/更新,但我对删除许多对象时所看到的内容感到困惑(例如,删除一个包含数百个与之相关的任务对象的项目).
在那种情况下,保存是异步的,但看起来主线程进入信号量等待情况(如我暂停调试器时所见)并且被有效阻止(我无法在UI中滚动),直到后台私有上下文完成保存.
实际上,我只是注意到单个对象的滑动删除删除会产生明显的延迟,尽管这种异步保存模式,所以看起来应用程序中的所有删除都很慢.
或者,如果我分配一个新的NSPrivateQueueConcurrencyType上下文,将其持久存储协调器设置为AppDelegate中的主PSC,并执行删除和保存,它仍然会做很多工作,但UI永远不会被阻止(但我不得不担心关于协调上下文,在主要上下文中重新获取).
我可能做错了什么想法,或者你也见过这种行为?
我们偶尔会从我们的用户那里得到崩溃报告(我们正在使用一个崩溃报告包,将崩溃发送到我们的服务器),并显示以下错误:
“非法尝试在不同上下文中的对象之间建立关系 '...'”
(不同的报告可能有不同的关系,并不是所有的报告都一样)。
这似乎很容易,除了:
我们的代码中只有一个 NSManagedObject——来自 App 委托的单例。
除了主线程,我们不使用任何线程。
所有对象都是使用上下文 using 分配的initWithEntity:insertIntoManagedObjectContext:(它们都不是用简单的 init 分配的)。
在我们的测试(数千次运行)中从未发生过错误。
所以基本上我们被卡住了。
任何想法将不胜感激。
我对 NSManagedObjectContextConcurrencyType 的文档没有任何意义。我将在以下情况下使用哪种类型,为什么?
- (void)viewDidLoad
{
self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:???];
[self loadRecordsFromCoreData];
}
- (void)loadRecordsFromCoreData {
[self.managedObjectContext performBlockAndWait:^{
//[self.managedObjectContext reset]; //do I need to do this?
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Item"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"display == YES"];
[request setPredicate:predicate];
[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES]]];
self.items = nil;
self.items = [self.managedObjectContext executeFetchRequest:request error:&error];
}];
[self displayItems];
}
Run Code Online (Sandbox Code Playgroud)
-displayItems 将根据 self.items 数组中对象的属性显示视图,例如 item.image、item.title、item.descriptionText 等。
我正在编写一个执行一些CoreData内容的函数.我希望函数只在所有CoreData操作执行后才返回.CoreData的东西包括在后台上下文中创建一个对象,然后在父上下文中做更多的东西:
+ (void) myFunction
NSManagedObjectContext *backgroundContext = [DatabaseDelegate sharedDelegate].backgroundContext;
[backgroundContext performBlockAndWait:^{
MyObject *bla = create_my_object_in:backgroundContext;
[backgroundContext obtainPermanentIDsForObjects:[[backgroundContext insertedObjects] allObjects] error:nil];
[backgroundContext save:nil];
[[DatabaseDelegate sharedDelegate].parent.managedObjectContext performBlockAndWait:^{
[[DatabaseDelegate sharedDelegate].parent updateChangeCount:UIDocumentChangeDone];
// Do some more stuff
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:someOperation];
}];
}];
return;
}
Run Code Online (Sandbox Code Playgroud)
我希望回归只发生在之后[queue addOperation:someOperation].这似乎适用于大多数情况,但我有一个案例,当这个函数永远不会返回.好像它已陷入僵局,我怀疑这是因为performBlockAndWait.
我的问题是:
(1)有人可以解释为什么会出现这种僵局吗?
和
(2)实现相同功能的正确方法是什么?要求是myFunction仅在两个块都已执行后才返回.
谢谢!
问题简而言之
由于没有持久存储协调器的NSManagedObjectContext不支持setFetchBatchSize选择器,我使用了这篇文章的解决方案,它适用于某些问题,我想解决.

这是数据库方案和Coredata结构,括号中的术语.测试应用程序有两个屏幕:包含聊天列表的主表和包含消息列表的详细信息表.主屏幕使用获取控制器中的主MOC来显示表中的数据和工人MOC以创建聊天和消息.详细信息屏幕使用Fetch MOC显示表中的数据.
在主屏幕上创建一个带有消息的新聊天并通过调用保存在层次结构中的所有MOC上保存它后,我无法通过选定的聊天详细信息屏幕获取消息.我在控制台中获得的是:"CoreData:annotation:总取指执行时间:0行为0.0000秒".应用程序重启后可以获取此数据.
它似乎与Fetch MOC中的故障消息有关,该故障消息与Chats存在故障关系,该Chats具有与我在Main MOC中的Chats不同的objectID.因为当我在Fetch MOC中获取Chat对象然后用它来查找Messages时,一切正常.
如果有人可以帮我解决这个问题,我会很感激Fetch MOC,或者可以通过我自己的ID字段而不是使用关系来解决所有Object Graph概念并获取数据.
一些代码
这是在didFinishLaunchingWithOptions上完成的Coredata堆栈初始化:
- (void)initializeCoreDataStack
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"FaultsFetching" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_managedObjectModel];
_writerMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_writerMOC setUndoManager:nil];
[_writerMOC setPersistentStoreCoordinator:_persistentStoreCoordinator];
_mainThreadMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainThreadMOC setUndoManager:nil];
[_mainThreadMOC setParentContext:_writerMOC];
_fetchMainThreadMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_fetchMainThreadMOC setUndoManager:nil];
[_fetchMainThreadMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[_fetchMainThreadMOC setPersistentStoreCoordinator:_persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backgroundContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:_writerMOC];
NSURL *storeURL = [APP_DOC_DIR URLByAppendingPathComponent:@"FaultsFetching.sqlite"];
NSError *error = nil; …Run Code Online (Sandbox Code Playgroud) core-data objective-c nsfetchedresultscontroller nsmanagedobjectcontext ios
我正在使用核心数据在应用程序中进行一些后台处理.后台处理在子managedObjectContext上完成.上下文初始化
appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// the moc in appDelegate is created with .MainQueueConcurrencyType
mainThreadMOC = appDelegate.managedObjectContext!
backgroundMOC = NSManagedObjectContext(concurrencyType:NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
backgroundMOC?.parentContext = mainThreadMOC
Run Code Online (Sandbox Code Playgroud)
后台处理按以下方法完成:
// download all new transaction log entries
func syncItems() {
... set up the query object for parse
let moc = CoreDataStore.sharedInstance.backgroundMOC
// perform download
moc?.performBlock( {
self.runQuery(query) // Download stuff und do some core data work
})
}
Run Code Online (Sandbox Code Playgroud)
调试器显示块内的所有工作确实在后台线程中.
当我从主线程调用此函数并立即使用冗长的核心数据操作阻止主线程(用于测试目的)时,我看到后台线程停止并且仅在主线程空闲时继续执行.
// this is called from a view controller in the main thread
syncItems() // …Run Code Online (Sandbox Code Playgroud) 我正在寻找有关此事的帖子,但我不完全明白......有什么区别:
[context reset];
Run Code Online (Sandbox Code Playgroud)
和:
for (NSManagedObjectID *objId in objectIds) {
[context deleteObject:[context objectWithID:objId]];
}
Run Code Online (Sandbox Code Playgroud)
或者他们是等同的?
谢谢
Apple 文档不清楚(或者我找不到)关于在父 MOC 具有插入后保存时父子 MOC 会发生什么的情况。
我正在使用 MARCUS ZARRA 的http://martiancraft.com/blog/2015/03/core-data-stack/方法,顶部有一个 privateQMOC,而 childMainMOC 作为主线程。
问题
我通过后台 Internet 请求在 privateMOC 上调用 save 将 10,000 个对象添加到 privateMOC,但是在 childMainMOC 上下文上构建的任何 NSFetchedResultsControllers 在父级保存后永远不会调用我的委托。因此界面不会更新以显示 parentMOC 中的更改。
我想调用一些会更新 childMainMOC 中所有对象的东西 - 然后应该调用子控制器上的委托方法。
或者其他一些解决方案。
core-data nsfetchedresultscontroller nsmanagedobjectcontext ios
我正在尝试使用CoreData,但是当我将它添加到我的项目中时,我只获得了两个新方法:
- (NSPersistentContainer *)persistentContainer
Run Code Online (Sandbox Code Playgroud)
和
- (void)saveContext
Run Code Online (Sandbox Code Playgroud)
现在我无法使用旧的方法CoreData,我找不到任何有这些新方法和Objective-C的教程.如何CoreData使用persistentContainerObjective-c在Xcode 8中保存和获取数据?