2012-09-24 22 views
10

MagicalRecord 2.0.3 kullanıyorum ve verileri arka planda nasıl kaydedeceğimi gerçekten anlayamıyorum.Arka planda birden çok nesne nasıl oluşturulur?

belgelerine göre, böyle bir şey çalışması gerekir:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { 
    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 
}]; 

Ancak, hiçbir şey veritabanına kaydedilir. Ben birden fazla kişi buna benzer çözümler gönderme gördüm:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { 
    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 
} completion:^{ 
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
     [[NSManagedObjectContext defaultContext] saveNestedContexts]; 
    }]; 
}]; 

Bu benim veri kümesi ile (save ana iş parçacığı üzerinde olur çünkü ancak başvurum bir süre tepkisiz, veritabanında benim verileri kaydetmek yapar çok uzun olan yaklaşık 3 saniye.

Ben de bu denedim, ama aynı zamanda blok sonra kaydedilirken:

self.queue = [[NSOperationQueue alloc] init]; 

[self.queue addOperationWithBlock:^{ 
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread]; 

    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 

    [localContext saveNestedContexts]; 
}]; 

Ve son olarak, bu kod ile aynı blokaj etkisi:

dispatch_queue_t syncQueue = dispatch_queue_create("Sync queue", NULL); 
dispatch_async(syncQueue, ^{ 
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread]; 

    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 

    [[NSManagedObjectContext contextForCurrentThread] saveNestedContexts]; 
}); 

Yani, en iyi yolu nedir Bunu çözmek için? Arka planda yüzlerce nesne oluşturmam gerekiyor ve uygulamanın yanıt vermeye devam etmesi gerekiyor.

+0

işe yarayabilir yeni iç içe bağlamları MagicalRecord içinde tasarruf API'ler çok büyük hasara yol için başladık nasıl bir örnek bulabilirsiniz. Bu sorunların farkında olmasına rağmen ve bazı düzeltmeler şimdi tartışılıyor, ben her zaman önerilere açıkım. – casademora

+2

Belki de Core Data'yı MR gibi bir çerçeve olmadan kullanmanın en iyisi sizsiniz? – Hunter

+0

MagicalRecord'u kullanarak bir çözüm buldunuz mu? Aynı sorunları yaşıyorum (arka planda güncelleme yaparken UI kilitleniyor) ve bir çözüm bulamıyorum. Teşekkürler! – RyanG

cevap

6

MagicalRecord, arka planda çalışırken bir çocuk içeriği kullanır. Bu küçük değişiklikler için iyi çalışır, ancak büyük miktarlarda veri alırken aşırı ana iş parçacığı engelleme oluşturur.

Bunu yapmanın yolu, paralel bir NSManagedObjectContext kullanmak ve NSManagedObjectContextDidSaveNotification bildirimi ve mergeChangesFromContextDidSaveNotification yöntemiyle birleşmeyi yapmaktır. Burada performans testlerine bakın: http://floriankugler.com/blog/2013/5/11/backstage-with-nested-managed-object-contexts

İç içe geçmiş bir bağlamı kaydederken, her şeyin ana içeriğe kopyalanması gerekir. Bunun tersine, getirilmeyen nesneler (birleştirdiğiniz bağlamda), mergeChangesFromContextDidSaveNotification tarafından birleştirilmeyecektir. Bu onu daha hızlı yapan şeydir.

Bu sonuçları toplu olarak kaydedildikten ve bir NSFetchResultsController kullanarak hemen görüntülemek istiyorsanız, sorunlarla karşılaşabilirsiniz. Çözüm için aşağıdaki soruya bakın: fazla performans ipuçları için NSFetchedResultsController with predicate ignores changes merged from different NSManagedObjectContext

bu soruya bir göz atın: Implementing Fast and Efficient Core Data Import on iOS 5

Kendi bağlam oluşturmak.

NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] 
          initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[importContext setPersistentStoreCoordinator:yourPersistentStoreCoordinator]; 
[importContext setUndoManager:nil]; // For importing you don't need undo: Faster 

// do your importing with the new importContext 
// … 

NSError* error = nil; 
if(importContext.hasChanges) { 
    if(![importContext save:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    } 
} 

yönetilen nesne bağlamlara kaydeder için dinliyor emin olun.

[[NSNotificationCenter defaultCenter] 
       addObserver:singleton 
       selector:@selector(contextDidSave:) 
        name:NSManagedObjectContextDidSaveNotification object:nil]; 

contextDidSave'de: değişikliği kendiniz birleştirirsiniz. Hiç CoreData nesnelerle arka plan, herhangi bir iş yapmak gerekir eğer öyleyse

- (void) contextDidSave:(NSNotification*) notification 
{ 
    if(![notification.object isEqual:self.mainContext]) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.mainContext mergeChangesFromContextDidSaveNotification:notification]; 
    }); 
    } 
} 
+0

Bu nasıl çalışır? Ana iş parçamın, içe aktarılacak büyük miktarda veri nedeniyle engellenmesi sorunuyla karşı karşıya geliyorum. MagicalRecord kullanıyorum ama burada yazdığınız şeyi başarmayı başaramıyorsunuz ... – swalkner

+0

@swalkner Daha fazla ayrıntı sağlamak için cevabı düzenledim. – Onato

1

Yönetilen nesne bağlamları parçacığı güvenli değil (yani ana UI engellemeden uzun süren bir ithalat/ihracat fonksiyonu) Yapmak istediğiniz olacak bir arka plan iş parçacığı üzerinde.

Bu durumlarda arka plan iş parçacığında yönetilen yeni bir nesne bağlamı oluşturmanız, çekirdek veri işleminiz boyunca yinelemeniz ve değişikliklerin ana içeriğini bildirmeniz gerekir.

Bu burada

Core Data and threads/Grand Central Dispatch

İlgili konular