什么会导致错误返回null,这就是我所拥有的
+ (BOOL)saveContext:(NSManagedObjectContext *)context
{
NSError *error = nil;
if (![context save:&error])
{
DLog(@"ERROR %@, %@", error, [error userInfo]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry"
message:@"Error Saving the Data"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
return NO;
}
return YES;
}
Run Code Online (Sandbox Code Playgroud)
上面的方法是一个类方法,我不知道为什么错误没有任何信息.
这个方法就是这样调用的
[HSCoreDataUtility saveContext:self.managedObjectContext];
当一个modalViewController关闭并返回到NavigationController时,所以我需要保存上下文,但它通过一个错误,现在我想我已经知道它没有被保存的原因,但不应该错误给出我有一个线索?但是日志只是说"ERROR(null),(null)"
有什么想法吗
我在他的核心数据书中读过Marcus Zarra关于多线程的章节,并且仔细研究了他的示例代码.但他的代码和其他人,我已经找到其他地方似乎那些后台进程重点并不需要知道对方的.这些示例适用于导入树结构 - 但它们不涉及导入更通用(复杂)的结构,如有向非循环图.
在我的例子中,我试图解析一个C++类层次结构,并希望尽可能多地使用NSOperations.我想为每个遇到的类创建一个NSManagedObject实例,并且我想在保存一个时合并不同的NSManagedObjectContexts.
顺便说一句:我能够使用单个NSOperation来处理文件并一次解析一个文件.在这个实现中,在主线程的MOC上调用-mergeChangesFromContextDidSaveNotification的-mergeChanges:方法效果很好.
但理想情况下,我会对源文件进行一次NSOperation迭代,并生成NSOperations来解析每个文件.我尝试了几种方法 - 但似乎无法做到正确.最有希望的是让每个NSOperation观察NSManagedObjectContextDidSaveNotification.使用-mergeChanges:看起来像这样:
- (void) mergeChanges:(NSNotification *)notification
{
// If locally originated, then trigger main thread to merge.
if ([notification object] == [self managedObjectContext])
{
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
return;
}
// If not locally originated, then flag need to merge with in this NSOperation's thread.
[self setNeedsToMerge:YES];
[self setMergeNotification:notification]; …Run Code Online (Sandbox Code Playgroud) 我仍然是Core Data的新手,我试图理解为什么它需要传递一个NSManagedObjectContext.据我了解,传递上下文需要让多个线程不会影响同一背景,但我也是印象是,这种模式有时被认为是一个反模式,因为注意到这里.
核心数据理论上可以以线程安全的方式实现,以避免使用这种模式吗?其他ORM(例如Ruby的ActiveRecord)如何避免这种模式?例如,CoreData无法实现per-NSManagedObject保存方法,例如在此扩展中.这个轻量级框架不处理多线程,但NSManagedObjects不能使用某种内部GCD队列来支持它,它们没有暴露内部上下文?
对不起,如果我错过了什么重大的.
multithreading core-data objective-c nsmanagedobjectcontext ios
我知道Core Data不是线程安全的,并且与上下文关联的NSManagedObjectContext和NSManagedObjects不能从线程传递给线程.
但是,如果我的主线程上有NSManagedObjectContext,我可以在后台线程上创建一个NSManagedObject对象(没有将它附加到任何上下文 - 也就是说,只需在NSManagedObject上调用alloc/init),然后将该NSManagedObject传递回主线程并将其添加到上下文中?我已经查看了有关Core Data并发性的文档,但找不到任何说这种使用模式没问题的文档.
我有一个后台线程执行复杂的任务然后发布结果.结果是一个NSManagedObject子类,它包含一些属性:time,文件路径和成功或错误消息(作为字符串).我想在后台线程上创建结果对象,然后将其抛回主线程并将其添加到Core Data上下文中,它将在tableView中显示.
如果我无法在后台线程上创建managedObject,那么我需要创建一个字典,将字典传递给主线程,读取键,从这些值创建managedObject等等.如果可能的话,在后台线程上使用managedObject.
cocoa core-data objective-c nsmanagedobject nsmanagedobjectcontext
嗨:)我有一个类似的问题,如在多个选项卡
背景中使用相同的NSManagedObjectContext:
我的managedObjectContext(进一步的MOC)在我的appDelegate类中初始化并通过
myViewController.managedObjectContext = self.managedObjectContext;或在init方法中传递到多个选项卡,self.managedObjectContext = pContext;
流程是:第一个视图是一个简单的集合列表.使用NSFetchedResultsController(myViewController : UITableViewController<NSFetchedResultsControllerDelegate>)获取集合.通过选择一个,您可以更深入地导航,但仍然通过此MOC.
在下一个控制器(detailsViewController)中,我列出了这个集合的一些项目,我可以与之交互(例如设置开关).
我还有一个editObjectContext:
// DetailsViewController.m
NSManagedObjectContext* editingContext = [[NSManagedObjectContext alloc] init];
[editingContext setPersistentStoreCoordinator:[managedObjectContext persistentStoreCoordinator]];
self.editingObjectContext = editingContext;
Run Code Online (Sandbox Code Playgroud)
现在我的问题:因为我的视图必须旋转,我正在使用以下技巧:
// DetailsViewController.m
DetailsView *localAct = [[DetailsView alloc] initWithManagedObjectContext:managedObjectContext ... ]
DetailsView *localSen = [[DetailsView alloc] initWithManagedObjectContext:managedObjectContext ... ]
UITableView *localContainerView = [[UITableView alloc] init];
self.containerView = localContainerView;
[localContainerView release];
//[...]
[containerView addSubview:actuatorView];
self.tableView = containerView;
Run Code Online (Sandbox Code Playgroud)
我还有一个按钮来管理这些项目(其中哪些应显示,哪些不显示).这个按钮只是用新的fetchResult重新加载表.
// DetailsView.m
- (void) manageItems{
managing = !managing;
[viewController …Run Code Online (Sandbox Code Playgroud) 我有两个实例NSManagedObjectContext:一个在主线程中使用,另一个在后台线程中使用(通过NSOperation.)为了线程安全,这两个上下文只共享一个NSPersistentStoreCoordinator.
我遇到的问题是第一个上下文(在主线程上)中的挂起更改在-save执行之前不可用于第二个上下文.这是可以理解的,因为共享的持久性存储不会有副本NSManagedObjects由被跟踪-insertedObjects,-updatedObjects以及-deletedObjects被持久.
遗憾的是,这会给用户体验带来问题:任何未保存的更改都不会出现在后台线程中生成的(耗时)报告中.
我能想到的唯一解决方案是讨厌的:从第一个上下文中取出插入的,更新的和删除的对象,并将它们移植到第二个上下文的对象图上.数据集中有一些非常复杂的关系,所以我对这个方向犹豫不决.我希望有人在这里作为更好的解决方案.
core-data objective-c nsoperation nsmanagedobject nsmanagedobjectcontext
我们的应用程序中的数据库由嵌套了几层深层的对象组成.出于体系结构的原因,我们现在无法从此迁移出去.
大部分数据每天都会过期.随着数据库规模的扩大,我们的应用程序性能会下降.
因此,我们需要找到一种有效的方法来保持数据库的小型化(至少在本发行版中),我们正在考虑以下方法之一:
在applicationWillResignActive期间,通过迭代根级别的所有对象来删除NSManagedObjects,在每个对象上调用delete,然后允许将删除级联到3层"to-many"对象.这涉及一个上下文保存,将所有这些提交给DB.这通常需要10-20秒(在iPhone 4上)才能删除对象,而Springboard会在10秒后终止进程.这样做的一个主要缺点是,如果上下文保存在10秒超时之前没有完成,则每次用户运行应用程序时都不会删除任何内容并且数据库会继续增长.
删除didFinishLaunchingWithOptions或applicationDidBecomeActive中的整个sqlite文件,或者删除applicationWillResignActive中的整个sqlite文件.这会强制我们弹出应用程序视图控制器堆栈的根目录,以避免尝试显示已删除的数据.最大的缺点是应用程序必须下载并解析数据几秒钟,然后用户才能在下次启动应用程序时执行任何操作.
在用户点击Home或Power按钮后,使用beginBackgroundTaskWithExpirationHandler删除DB对象.与此相关的未知因素使其变得可怕.有人这样做(成功)吗?
在应用程序运行时以增量方式删除较小的对象组.这会增加设备的负载,从而破坏了tableviews的平滑性,使它们感到紧张.在删除旧对象的同时,API调用已经解析的数据量似乎不切实际.
任何关于删除核心数据中的对象的最佳实践的想法将不胜感激!
我正在尝试创建一个临时的托管对象上下文,在用户输入信息的几个屏幕之后,我将该上下文与主上下文合并(以确保没有插入"不完整"的对象).这是我创建临时上下文以及如何在其中插入对象的方法:
if (!self.someManagedObject) {
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:@[[NSBundle mainBundle]]];
NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[storeCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:nil];
NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:storeCoordinator];
self.someManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"SomeObject" inManagedObjectContext:managedObjectContext];
NSLog(@"%@", self.someManagedObject.managedObjectContext);
}
Run Code Online (Sandbox Code Playgroud)
这是其中的一部分viewDidLoad.在控制台中,它显示托管对象上下文具有值.
然而,就在这个if语句之后(即使在内viewDidLoad,self.someManagedObject.managedObjectContext也是nil.我可以看到为什么局部变量不再可用(它只是超出范围),但是仍然应该设置托管对象的属性,对吧?
我知道我可以创建一个属性来存储托管对象上下文,但我宁愿让它以这种方式工作.
我试验了这里描述的相同问题.问题是使用DEFAULT上下文的子MOC来保存coredata,90%的时候,主线程上下文中的结果会更新来自子MOC的更改,但有时它们不是.
在我的测试中,我反复写入相同的实体(不是太快,使用UI):广告实体(favorite_count)和广告与用户之间的最爱关系.
从DEFAULT Context的子MOC保存时,这是MagicalRecord的预期输出(我也打印了updatedObjects计数):
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]? ? ? ? ? ? ? ? ? ? ? ? ? ? POST FAVORITE ? ? ? ? ? ? ? ? ? ? ? ? ? ?
2013-09-19 11:40:35.154 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) ? Saving <NSManagedObjectContext (0xb8b55e0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-09-19 11:40:35.155 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) ? Save Parents? 1
2013-09-19 11:40:35.155 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) ? Save Synchronously? 1
2013-09-19 11:40:35.155 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) ? Updated objects = 4
2013-09-19 11:40:35.183 …Run Code Online (Sandbox Code Playgroud) core-data nsmanagedobjectcontext ios magicalrecord magicalrecord-2.1
使用,当我遇到有趣的行为来的NSManagedObjectContext的performBlock:与通知中心.
从主UI线程我触发异步数据下载(使用NSURLConnection的connectionWithRequest:).当数据到达时,将调用以下委托方法:
- (void)downloadCompleted:(NSData *)data
{
NSArray *new_data = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.backgroundObjectContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.backgroundObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
[self.backgroundObjectContext performBlockAndWait:^{
[self saveToCoreData:new_data];
}];
}
Run Code Online (Sandbox Code Playgroud)
该savetoCoreData:方法只是将新数据保存到后台上下文:
- (void)saveToCoreData:(NSArray*)questionsArray
{
for (NSDictionary *questionDictionaryObject in questionsArray) {
Question *newQuestion = [NSEntityDescription
insertNewObjectForEntityForName:@"Question"
inManagedObjectContext:self.backgroundObjectContext];
newQuestion.content = [questionDictionaryObject objectForKey:@"content"];
}
NSError *savingError = nil;
[self.backgroundObjectContext save:&savingError];
}
Run Code Online (Sandbox Code Playgroud)
在视图控制器中,viewDidLoad我将观察者添加到通知中心:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
Run Code Online (Sandbox Code Playgroud)
然后在contexChanged:我合并背景上下文与主上下文,以便调用我的NSFetchedResultsController的委托方法,我的视图可以更新:
- (void)contextChanged:(NSNotification*)notification
{ …Run Code Online (Sandbox Code Playgroud) core-data nsfetchedresultscontroller nsnotificationcenter nsmanagedobjectcontext ios