Iphone iOS 5核心数据冻结
我尝试做以下简单的事情:Iphone iOS 5核心数据冻结,iphone,core-data,ios5,Iphone,Core Data,Ios5,我尝试做以下简单的事情: NSArray * entities = [context executeFetchRequest:inFetchRequest error:&fetchError]; 没什么特别的。但这在iOS 5中冻结,在iOS 4中运行良好。我没有收到异常、警告或错误;我的应用程序只是简单地冻结 请帮帮我!我要死在这里了!;) 我不知道您是否也使用不同的线程。如果是,则问题来自NSManagedObject本身不是线程安全的。在主线程上创建ManagedContext并
NSArray * entities = [context executeFetchRequest:inFetchRequest error:&fetchError];
没什么特别的。但这在iOS 5中冻结,在iOS 4中运行良好。我没有收到异常、警告或错误;我的应用程序只是简单地冻结
请帮帮我!我要死在这里了!;) 我不知道您是否也使用不同的线程。如果是,则问题来自NSManagedObject本身不是线程安全的。在主线程上创建ManagedContext并在另一个线程上使用它会冻结该线程 或许本文可以帮助您: Apple有一个用于在多个线程(通常是主线程和后台线程)上处理Coredata的演示应用程序: 我为解决这个问题所做的是:
- 在应用程序委托中:创建持久存储(一个用于所有线程)并为主线程创建Coredata托管上下文
- 在后台线程中,创建一个新的托管上下文(来自同一个持久存储)
- 保存时使用通知,以便让mainContext知道后台线程何时完成(插入行或其他)
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.cdw = [[CoreDataWrapper alloc] initWithPersistentStoreCoordinator:[self persistentStoreCoordinator] andDelegate:self];
remoteSync = [RemoteSync sharedInstance];
...
[self.window addSubview:navCtrl.view];
[viewController release];
[self.window makeKeyAndVisible];
return YES;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator == nil) {
NSURL *storeUrl = [NSURL fileURLWithPath:self.persistentStorePath];
NSLog(@"Core Data store path = \"%@\"", [storeUrl path]);
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
NSError *error = nil;
NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error];
NSAssert3(persistentStore != nil, @"Unhandled error adding persistent store in %s at line %d: %@", __FUNCTION__, __LINE__, [error localizedDescription]);
}
return persistentStoreCoordinator;
}
-(NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext == nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
}
return managedObjectContext;
}
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator == nil) {
NSURL *storeUrl = [NSURL fileURLWithPath:self.persistentStorePath];
NSLog(@"Core Data store path = \"%@\"", [storeUrl path]);
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
NSError *error = nil;
NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error];
NSAssert3(persistentStore != nil, @"Unhandled error adding persistent store in %s at line %d: %@", __FUNCTION__, __LINE__, [error localizedDescription]);
}
return persistentStoreCoordinator;
}
-(NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext == nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
}
return managedObjectContext;
}
-(NSString *)persistentStorePath {
if (persistentStorePath == nil) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths lastObject];
persistentStorePath = [[documentsDirectory stringByAppendingPathComponent:@"mgobase.sqlite"] retain];
}
return persistentStorePath;
}
-(void)importerDidSave:(NSNotification *)saveNotification {
if ([NSThread isMainThread]) {
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
} else {
[self performSelectorOnMainThread:@selector(importerDidSave:) withObject:saveNotification waitUntilDone:NO];
}
}
在运行后台线程的对象中:
monitor = [[NSThread alloc] initWithTarget:self selector:@selector(keepMonitoring) object:nil];
-(void)keepMonitoring{
while(![[NSThread currentThread] isCancelled]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
AppDelegate * appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//creating the cdw here will create also a new managedContext on this particular thread
cdwBackground = [[CoreDataWrapper alloc] initWithPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator andDelegate:appDelegate];
...
}
}
希望这有帮助,
M.我也有同样的问题。如果在调试器下运行且应用程序“挂起”时停止应用程序(使用调试器上的“暂停”按钮)。如果您在executeFetchRequest行,则检查上下文变量。如果它具有ivar\u objectStoreLockCount且大于1,则它将等待关联存储上的锁
在某个地方,您正在关联存储上创建竞争条件。这听起来确实像是试图从创建它的线程/队列以外的线程/队列访问
NSManagedObjectContext
。正如其他人建议的那样,您需要查看线程并确保遵循核心数据的规则。谢谢您的提示本页将介绍如何解决从iOS4升级时出现的冻结问题。这是我开始在iOS上编程以来发现的最烦人的问题
我已经找到了一个快速的解决方案,可以解决其他线程只调用了几个上下文的情况
我只使用performSelectorOnMainThread
[self performSelectorOnMainThread:@selector(stateChangeOnMainThread:) withObject: [NSDictionary dictionaryWithObjectsAndKeys:state, @"state", nil] waitUntilDone:YES];
要检测从另一个线程调用上下文的位置,您可以在调用上下文的函数的NSLog上设置断点,如下面的代码段所示,只需在这些函数上使用performSelectorOnMainThread
if(![NSThread isMainThread]){
NSLog(@"Not the main thread...");
}
我希望这可能会有所帮助……执行获取请求必须从创建上下文的线程开始 请记住,它不是线程安全的,尝试从另一个线程执行
executeFetchRequest
将导致不可预知的行为
要正确执行此操作,请使用
[context performBlock: ^{
NSArray * entities = [context executeFetchRequest:inFetchRequest error:&fetchError];
}];
这将
executeFetchRequest
在与上下文相同的线程中,它可能是主线程,也可能不是主线程。在我的情况下,应用程序将在没有任何警告的情况下冻结在“executeFetchRequest”之前。解决方案是将所有数据库操作包装在@synchronized(persistentStore)中。
例如:
使用fetchrequest删除所有对象对我不起作用,sqlite看起来已损坏。我找到的唯一方法是
//Erase the persistent store from coordinator and also file manager.
NSPersistentStore *store = [self.persistentStoreCoordinator.persistentStores lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
[self.persistentStoreCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
//Make new persistent store for future saves (Taken From Above Answer)
if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}
它是冻结还是崩溃?两者都不能。如果它崩溃,会有崩溃日志或堆栈跟踪。你没有在线程之间共享上下文,是吗?@Dries-我也在调查这个原因,我发现了相同的行为。如果你在4.3模拟器上运行,它工作正常吗(我的正常)?在5.0模拟器上,它会定期锁定,没有错误消息或调试信息。我还没有答案,但我已经跟踪到这样一个事实:当它挂起时,如果你在调试器下运行,并且你破坏了应用程序,它会停在executeFetchRequest行。如果你检查managedObjectContext(上下文)在你的例子中,我发现其中一个内部vars\u objectStoreLockCount设置为2。这告诉我它正在等待一个锁。这肯定是iOS5现在处理并发性的一个问题-我仔细查看了我的代码,它看起来不漂亮超级漂亮的提示ferdil!谢谢!我得到了同样的冻结,但我肯定没有线程因此调用performSelectorOnMainThread不会改变任何事情。可能这是另一个问题。如果在应用程序冻结时暂停调试器,您将看到调试器停止的位置。如果您可以从不同于线程1的线程访问CoreDataModel上下文,则这是seme问题,您可以通过这种方式解决。否则您可能需要进一步搜索问题,以确定并解决它。
//Erase the persistent store from coordinator and also file manager.
NSPersistentStore *store = [self.persistentStoreCoordinator.persistentStores lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
[self.persistentStoreCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
//Make new persistent store for future saves (Taken From Above Answer)
if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// do something with the error
}