iphone - iOS 5 核心数据卡住

标签 iphone core-data ios5

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

NSArray * entities = [context executeFetchRequest:inFetchRequest error:&fetchError];

没什么特别的。但这在 iOS 5 中卡住,在 iOS 4 中工作正常。我没有收到异常、警告或错误;我的应用程序只是卡住了。

请帮帮我!我快死在这里了! ;)

最佳答案

不知道你是否也使用不同的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

我为解决此问题所做的工作是:

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

有几种解决方案,使用 NSQueueOperation。就我而言,我正在使用 while 循环。这是我的代码,如果它可以帮助你。不过,Apple 关于并发性的文档及其热门歌曲示例应用程序是很好的起点。

在应用程序委托(delegate)中:

 -(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.

关于iphone - iOS 5 核心数据卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7807977/

相关文章:

iphone - EKEvent 在 iOS5 中损坏?

iphone - 访问未知的setter方法

core-data - 核心数据对象在其相关对象的属性更改时更新

ios - 通过 NSManagedObjectSubclass 上的 Swift 计算属性对 NSFetchedResultsController 进行排序

ios - 如何在警报 View 中存储文本字段中的 uitextfield 值?

ios - 在谷歌地图上定位标记

iphone - 沿x和y轴移动UIImage

ios - 如何告诉 Xcode 将 CoreData 输出刷新到 Sqlite

ios - 在 Storyboard 中加载 ViewController

ios5 - self.presentingViewController 返回 UITabBarController 而不是 View Controller 用 presentModalViewController 推送它