核心数据和线程/ Grand Central Dispatch

Rui*_*pes 40 iphone multithreading core-data grand-central-dispatch ios

我是Grand Central Dispatch(GCD)和Core Data的初学者,我需要你的帮助来使用带有CGD的Core Data,这样当我向Core Data添加40.000条记录时,UI不会被锁定.

我知道CD不是线程安全的,所以我必须使用另一个上下文,然后保存数据和合并上下文,就我从一些文章中能够理解的那样.

我还做不到的是把各个部分放在一起.

所以,在我的代码中,我需要你的帮助,如何做到这一点.

我有:

/*some other code*/

for (NSDictionary *memberData in arrayWithResult) {

    //get the Activities for this member
    NSArray *arrayWithMemberActivities = [activitiesDict objectForKey:[memberData objectForKey:@"MemberID"]];

    //create the Member, with the NSSet of Activities
    [Members createMemberWithDataFromServer:memberData
                         andActivitiesArray:arrayWithMemberActivities
                              andStaffArray:nil
                           andContactsArray:nil
                     inManagedObjectContext:self.managedObjectContext];
}
Run Code Online (Sandbox Code Playgroud)

如何将其转换为在后台工作,然后,在完成保存后,保存数据并更新UI,而不会在保存40.000对象时阻止UI?

Rog*_*Rog 57

这是您尝试的一个很好的例子.如果您有任何疑问,请随时回来:

self.mainThreadContext... // This is a reference to your main thread context
NSPersistentStoreCoordinator *mainThreadContextStoreCoordinator = [self.mainThreadContext persistentStoreCoordinator];
dispatch_queue_t request_queue = dispatch_queue_create("com.yourapp.DescriptionOfMethod", NULL);
dispatch_async(request_queue, ^{

    // Create a new managed object context
    // Set its persistent store coordinator
    NSManagedObjectContext *newMoc = [[NSManagedObjectContext alloc] init];
    [newMoc setPersistentStoreCoordinator:mainThreadContextStoreCoordinator]];

    // Register for context save changes notification
    NSNotificationCenter *notify = [NSNotificationCenter defaultCenter];
    [notify addObserver:self 
               selector:@selector(mergeChanges:) 
                   name:NSManagedObjectContextDidSaveNotification 
                 object:newMoc];

    // Do the work
    // Your method here
    // Call save on context (this will send a save notification and call the method below)
    BOOL success = [newMoc save:&error];
    if (!success)
        // Deal with error
    [newMoc release];
});
dispatch_release(request_queue);
Run Code Online (Sandbox Code Playgroud)

并响应上下文保存通知:

- (void)mergeChanges:(NSNotification*)notification 
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mainThreadContext mergeChangesFromContextDidSaveNotification:notification waitUntilDone:YES];
    });
}
Run Code Online (Sandbox Code Playgroud)

完成后台线程上下文后,不要忘记从通知中心删除观察者.

[[NSNotificationCenter defaultCenter] removeObserver:self];
Run Code Online (Sandbox Code Playgroud)


bry*_*mac 8

这是一个以最简单的术语涵盖GCD和UI的片段.您可以将doWork替换为执行CoreData工作的代码.

关于CD和线程的安全性,关于GCD的一个很好的部分是,您可以对应用程序的各个区域(子系统)进行分区以进行同步并确保它们在同一队列上执行.您可以在名为com.yourcompany.appname.dataaccess的队列上执行所有CoreData工作.

在示例中,有一个按钮调用长时间运行的工作,一个状态标签,我添加了一个滑块,以显示我可以在bg工作完成时移动滑块.

// on click of button
- (IBAction)doWork:(id)sender
{
    [[self feedbackLabel] setText:@"Working ..."];
    [[self doWorkButton] setEnabled:NO];

    // async queue for bg work
    // main queue for updating ui on main thread
    dispatch_queue_t queue = dispatch_queue_create("com.sample", 0);
    dispatch_queue_t main = dispatch_get_main_queue();

    //  do the long running work in bg async queue
    // within that, call to update UI on main thread.
    dispatch_async(queue, 
                   ^{ 
                       [self performLongRunningWork]; 
                       dispatch_async(main, ^{ [self workDone]; });
                   });

    // release queues created.
    dispatch_release(queue);    
}

- (void)performLongRunningWork
{
    // simulate 5 seconds of work
    // I added a slider to the form - I can slide it back and forth during the 5 sec.
    sleep(5);
}

- (void)workDone
{
    [[self feedbackLabel] setText:@"Done ..."];
    [[self doWorkButton] setEnabled:YES];
}
Run Code Online (Sandbox Code Playgroud)