Podstawowe Dane i wątki / Grand Central Dispatch

Jestem początkujący z Grand Central Dispatch (GCD) i Core Data, i potrzebuję twojej pomocy, aby korzystać z Core Data z CGD, tak, że interfejs nie jest zablokowany, podczas gdy dodaję 40.000 rekordów do Core Data.

Wiem, że CD nie jest bezpieczny dla wątków, więc muszę użyć innego kontekstu, a następnie zapisać dane i scalić konteksty, o ile byłem w stanie zrozumieć z niektórych artykułów.

To, czego jeszcze nie mogłem zrobić, to poskładać kawałki do kupy.

Więc w moim kodzie potrzebuję twojej pomocy, jak to.

Mam:

/*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];
}

Jak Mogę przekształcić to do pracy w tle, a następnie, po zakończeniu zapisywania, zapisać dane i zaktualizować interfejs użytkownika, bez blokowania interfejsu podczas zapisywania 40.000 obiektów?

Author: Monolo, 2011-09-24

6 answers

Oto dobry przykład dla Ciebie. W razie jakichkolwiek pytań zapraszamy do kontaktu:

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);

I w odpowiedzi na powiadomienie o zapisie kontekstu:

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

I nie zapomnij usunąć obserwatora z Centrum powiadomień, gdy skończysz z kontekstem wątku tła.

[[NSNotificationCenter defaultCenter] removeObserver:self];
 57
Author: Rog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-18 06:33:58

Oto fragment, który obejmuje GCD i UI w najprostszych terminach. Możesz zastąpić doWork swoim kodem, który działa w CoreData.

Jeśli chodzi o bezpieczeństwo płyt CD i wątków, jedną z fajnych części GCD jest możliwość wyłączenia obszarów aplikacji (podsystemów), aby zsynchronizować je i upewnić się, że zostaną wykonane w tej samej kolejce. Możesz wykonać całą pracę CoreData w kolejce o nazwie com.Twoja firma.nazwa aplikacji.dostęp do danych.

W próbce znajduje się przycisk wywołujący długie uruchomiona praca, Etykieta stanu i dodałem suwak, aby pokazać, że mogę przesuwać suwak, gdy praca bg jest wykonywana.

// 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];
}
 8
Author: bryanmac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-26 20:23:26

Ten wpis na blogu zawiera szczegółowy opis współbieżności podstawowych danych i przykładowego kodu: http://www.duckrowing.com/2010/03/11/using-core-data-on-multiple-threads/

 3
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-25 13:37:32

Dodanie kolejnego źródła informacji można sprawdzić

ThreadedCoreData

[[0]} przykładowy kod biblioteki programistów Apple iOS, który został ostatnio zaktualizowany (2013-06-09)

Pokazuje, jak używać podstawowych danych w środowisku wielowątkowym, zgodnie z pierwszym zalecanym wzorcem wspomnianym w danych podstawowych Poradnik Programowania.

Na podstawie próbki SeismicXML pobiera i przetwarza kanał RSS ze Stanów Zjednoczonych Ankieta (USGS), która dostarcza danych na temat ostatnie trzęsienia ziemi na całym świecie. Co wyróżnia tę próbkę czy to, że uporczywie przechowuje trzęsienia ziemi za pomocą podstawowych danych. Za każdym razem uruchamiasz aplikację, pobiera nowe dane o trzęsieniu ziemi, przetwarza je w NSOperation, która sprawdza duplikaty i przechowuje nowo założone trzęsienia ziemi jako zarządzane obiekty.

Dla nowych danych, pomocne może być porównanie SeismicXML próbki z tej próbki i zauważyć niezbędne składniki na wprowadź Podstawowe Dane do aplikacji.

 1
Author: plusangel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-22 10:24:22

Więc wybrana odpowiedź na to pytanie pochodzi z prawie 2 lat temu i jest z tym kilka problemów:

  1. nie jest przyjazny dla ARC-trzeba usunąć wywołanie release na newMoc - ARC nie będzie się nawet kompilował z tym
  2. powinieneś tańczyć weakSelf / strongSelf wewnątrz bloku - w przeciwnym razie prawdopodobnie tworzysz pętlę zachowawczą na kreacji obserwatora. Zobacz tutaj doc Apple: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html
  3. @ RyanG zapytał w komentarzu dlaczego blokuje. Domyślam się, że ostatnio edytowana metoda ma waitUntilDone:tak-tyle że to zablokuje główny wątek. Prawdopodobnie chcesz waitUntilDone: nie, ale nie wiem, czy są aktualizacje UI odpalania z tych zdarzeń zmian, jak również, więc wymagałoby testuję.

-- Edit--

Patrząc dalej na #3-waitUntilDone: YES nie jest poprawną methodSignature dla zarządzanych obiektów kontekstowych, więc jak to w ogóle działa?

 0
Author: Matt S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-23 03:18:28

O wiele łatwiejszy sposób, niż dołączenie stałego koordynatora sklepu do nowego kontekstu, który również nie jest bezpieczny dla wątku, btw.

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrency];
[context setParentContext:<main thread context here>];

[context performBlock:^{

    ...
    // Execute all code on current context
    ...

}];

NSError *error = nil;
[context save:&error];
if (!error) {
    [context.parentContext save:&error];
    if (error) {
        NSLog(@"Could not save parent context: %@", error);
    }
}
else {
    NSLog(@"Could not save context: %@", error);
}

Świetny tutorial Jak korzystać z danych Wielotematycznych:

Http://www.cocoanetics.com/2012/07/multi-context-coredata/

 0
Author: Simon Germain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-23 03:35:59