iOS 5核心数据冻结

Dri*_*met 26 iphone core-data ios5

我尝试做以下简单的事情:

NSArray * entities = [context executeFetchRequest:inFetchRequest error:&fetchError];
Run Code Online (Sandbox Code Playgroud)

没有什么花哨.但这在iOS 5中冻结,它在iOS 4中运行良好.我没有异常,警告或错误; 我的应用程序只是冻结.

请帮帮我!我快死了!;)

Mic*_* A. 19

我不知道你是否也使用不同的Thread.如果是,则问题来自NSManagedObjects本身不是线程安全的事实.在主线程上创建ManagedContext并在另一个线程上使用它会冻结线程.

也许这篇文章可以帮到你:http: //www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/

Apple有几个线程(通常是主线程和后台线程)处理Coredata的演示应用程序:http://developer.apple.com/library/ios/#samplecode/TopSongs/Introduction/Intro.html

我为解决这个问题所做的是:

  • 在应用程序委托中:创建持久存储(一个用于所有线程)并为主线程创建Coredata托管上下文,
  • 在后台线程中,创建一个新的托管上下文(来自同一个持久性存储)
  • 保存时使用通知,让mainContext知道后台线程何时完成(插入行或其他).

有几种解决方案,使用NSQueueOperation.对于我的情况,我正在使用while循环.这是我的代码,如果它可以帮助你.但是,关于并发性的Apple文档及其Top Songs示例应用程序是很好的起点.

在应用程序委托中:

 -(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];
    }
}
Run Code Online (Sandbox Code Playgroud)

在运行后台线程的对象中:

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];
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这有帮助,

M.


Car*_*dal 11

感谢本页提供的有关如何解决从iOS4升级时出现的冻结问题的提示.自从我开始在iOS上编程以来,它一直是我发现的最烦人的问题.

我找到了一个快速解决方案,用于从其他线程调用上下文的几个案例.

我只是使用performSelectorOnMainThread:

    [self performSelectorOnMainThread:@selector(stateChangeOnMainThread:) withObject: [NSDictionary dictionaryWithObjectsAndKeys:state, @"state", nil] waitUntilDone:YES];
Run Code Online (Sandbox Code Playgroud)

要检测从另一个线程调用上下文的位置,您可以在NSLog上为您调用上下文的函数放置一个断点,如下面的代码段所示,只需对它们使用performSelectorOnMainThread即可.

if(![NSThread isMainThread]){
     NSLog(@"Not the main thread...");
}
Run Code Online (Sandbox Code Playgroud)

我希望这可能会有所帮助......


fer*_*dil 6

我遇到过同样的问题.如果你在调试器下运行,当应用程序"挂起"时停止应用程序(使用调试器上的"暂停"按钮.如果你在executeFetchRequest行,那么检查上下文变量.如果它有一个ivar _objectStoreLockCount及其大于1,然后等待关联商店的锁定.

在某处您正在关联商店中创建竞争条件.