SORU
10 Mayıs 2012, PERŞEMBE


Uygulama Hızlı ve Verimli Çekirdek Veri iOS 5 Al

SoruNasıl benim NSFetchedResultsController UI güncellemek için tetikleyici böylece çocuğum değişiklikleri ana içeriği üzerinde kalıcı görmek için bağlam alabilirim?

İşte kurulum:

Ve XML veri (yaklaşık 2 milyon albüm, metin normal bir paragraf kabaca her boyutta) çok indirilenler ekleyen bir uygulama var .sqlite dosya boyutu yaklaşık 500 MB olur. Çekirdek Veri içine bu içerik eklemek zaman alır, ancak kullanıcı veri deposu kademeli içine yüklenirken app kullanmak mümkün olmak istiyorum. Hayır kilitleniyor çok büyük miktarda veri etrafında hareket ediliyor ve kullanıcıya görünmeyen belli belirsiz olmalı, sinirlilik: tereyağı gibi kayar. Yine de, uygulamayı daha kullanışlı, daha fazla veri eklenir, bu verileri Temel Veri deposuna eklenmesi için sonsuza kadar bekleyemeyiz. Kod bu gerçekten alma kodu bu kodu kaçınmak istiyorum

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];

Uygulamayı desteklemek için gereken en yavaş cihaz iPhone 3G ise sadece iOS 5.

İşte benim geçerli çözüm geliştirmek için şimdiye kadar kullandığım kaynaklar:

Apple's Core Data Programming Guide: Efficiently Importing Data

  • Autorelease Havuzları bellek tutmak için kullanın
  • İlişkiler Mal Oldu. İthalat düz, sonra sonunda ilişkileri düzeltme
  • Eğer yardımı olacaksa sorgu yok, (n^2) O bir şekilde aşağı şeyler yavaşlatır
  • Toplu ithalat: save, reset, tahliye ve tekrarlayın
  • İthalat Yöneticisi Geri kapatın

iDeveloper TV - Core Data Performance

  • Kullanım 3 Kaynaklar: Ana, Ana ve Doğumdan içerik türleri

iDeveloper TV - Core Data for Mac, iPhone & iPad Update

  • PerformBlock ile diğer sıralarını kaydeder çalışan her şey çok hızlı yapar.
  • Şifreleme şey, eğer kapatın yavaşlatır.

Importing and Displaying Large Data Sets in Core Data by Marcus Zarra

  • Geçerli çalışma döngü için zaman vermek suretiyle al aşağı yavaş olabilir şey kullanıcı için pürüzsüz hissediyorum.
  • Örnek Kod büyük ithalat ve UI duyarlı, ama hızlı olarak 3 bağlamlar ve zaman uyumsuz disk kurtarmak için mümkün olduğunu kanıtlıyor.

Benim Geçerli Çözüm

NSManagedObjectContext 3 örnekleri var:

masterManagedObjectContext- Bu NSPersistentStoreCoordinator ve diske kaydetmek için sorumlu olan içerik. Benim uyumsuz olabilir ve bu nedenle çok hızlı kaydeder bu yüzden bunu yapıyorum. Böyle fırlatma üzerinde oluşturun:

masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[masterManagedObjectContext setPersistentStoreCoordinator:coordinator];

mainManagedObjectContext- Bu UI her yerde kullanır bağlam budur. Bu masterManagedObjectContext bir çocuk. Ben böyle oluşturun:

mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[mainManagedObjectContext setUndoManager:nil];
[mainManagedObjectContext setParentContext:masterManagedObjectContext];

backgroundContext- Bu bağlamda Temel Veri XML Verisi alma sorumlu NSOperation benim alt oluşturulur. Operasyonun ana yöntem olarak bunu oluşturmak ve ana içerik için bağlantı.

backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundContext setUndoManager:nil];
[backgroundContext setParentContext:masterManagedObjectContext];

Bu gerçekten çok, ÇOK hızlı çalışır. Sadece 3 içerik bu Kur yaparak üzerinde 10x import benim hızını artırmak için mümkün oldu! Dürüst olmak gerekirse, buna inanmak zor. (Bu temel tasarım standart Temel Veri şablonu...) bir parçası olmalıdır

Alma işlemi sırasında Kaydet 2 farklı yolu. Arka plan içerik biriktiriyorum her 1000 öğeleri:

BOOL saveSuccess = [backgroundContext save:&error];

O zaman alma işlemi sonunda, görünüşte, ana bağlam da dahil olmak üzere diğer alt kapsamları için: değişiklikleri iter ana/üst bağlama biriktiriyorum

[masterManagedObjectContext performBlock:^{
   NSError *parentContextError = nil;
   BOOL parentContextSaveSuccess = [masterManagedObjectContext save:&parentContextError];
}];

SorunSorun benim UI görünüm yükler yüklemez kadar güncelleme olmayacak.

Fed veri NSFetchedResultsController kullanarak bir UİTableView ile basit bir UİViewController var. Alma işlemi tamamlandığında, NSFetchedResultsController UI görmeye alışık olduğum gibi otomatik güncelleme yok yani üst/ana içerikten herhangi bir değişiklik görelim. Yığın ve yeniden yükleme kapalı UİViewController ben pop eğer tüm verileri var.

SoruNasıl benim NSFetchedResultsController UI güncellemek için tetikleyici böylece çocuğum değişiklikleri ana içeriği üzerinde kalıcı görmek için bağlam alabilirim?

Sadece app çöken aşağıdaki denedim:

- (void)saveMasterContext {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];    
    [notificationCenter addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];

    NSError *error = nil;
    BOOL saveSuccess = [masterManagedObjectContext save:&error];

    [notificationCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];
}

- (void)contextChanged:(NSNotification*)notification
{
    if ([notification object] == mainManagedObjectContext) return;

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
        return;
    }

    [mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

CEVAP
11 Mayıs 2012, Cuma


Muhtemelen atılımlar ana MOC de kaydetmeniz gerekir. Kurtarmak için hiçbir şey ifade MOC sonuna kadar beklemek zorunda. Kendi iş parçacığı ve bellek de aşağı tutmaya yardımcı olacaktır.

Yazdı:

O zaman alma sürecinin sonunda, ana/üst biriktiriyorum görünürde, değişiklikleri diğer çocuğa dışarı iter hangi bağlam kapsamları ana içeriği dahil

Yapılandırma, iki çocuk (ana ve arka plan MOC MOC), "master." hem üstü var

Bir çocuk kaydetmek, değişiklikleri kadar üst içine iter. Bu MOC diğer çocukları veri getirme gerçekleştirdikleri bir dahaki sefere göreceksiniz... açıkça haberdar değiller.

BG kaydettiğinde, ANA Veri itti. Bu verilerin hiçbiri MASTER kaydeder kadar diskte olduğunu unutmayın. Ayrıca, herhangi bir yeni öğeler MASTER diske kaydeder kadar kalıcı Kimlikleri değil.

Senin senaryoda, DidSave bildirimi sırasında tasarruf ustasından birleştirerek ANA MOC verileri çekersiniz.

Bu "asılı." nerede olduğunu çok merak ediyorum, çok çalışmalı Kurallı şekilde ana MOC iplik (en az iOS 5 için) üzerinde çalışan olmadığını not edeceğim.

Ayrıca, muhtemelen sadece ana MOC sadece kayıt için değil gibi görünüyor olsa da) gelen değişiklikleri birleştirme de ilgilendi. - - - Tasarruf güncelleme bildirim kullanmak için olsaydı, bunu yapardım...

- (void)contextChanged:(NSNotification*)notification {
    // Only interested in merging from master into main.
    if ([notification object] != masterManagedObjectContext) return;

    [mainManagedObjectContext performBlock:^{
        [mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];

        // NOTE: our MOC should not be updated, but we need to reload the data as well
    }];
}

Şimdi, asmak ile ilgili gerçek sorun ne olabilir... iki farklı arama ana kaydetmeye göster. ilk iyi korunan kendi performBlock, ama ikinci (saveMasterContext bir performBlock arama olabilirsin . ama değil

Ancak, aynı zamanda bu kodu değiştirmek istiyorum.

- (void)saveMasterContext {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];    
    [notificationCenter addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];

    // Make sure the master runs in it's own thread...
    [masterManagedObjectContext performBlock:^{
        NSError *error = nil;
        BOOL saveSuccess = [masterManagedObjectContext save:&error];
        // Handle error...
        [notificationCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];
    }];
}

Ancak, ANA bir çocuk olduğunu unutmayın. Yani, değişiklikleri birleştirmek için olmamalıdır. Bunun yerine, sadece asıl DidSave izle, sadece refetch! Veri ailen zaten, sadece bunun için sormak için bekliyor. İlk etapta üst verilere sahip olmanın avantajlarından biri.

Başka bir alternatif düşünün (ve sonuçları hakkında çok fazla veri var ... duymak isterim)...

Arka plan EFENDİ bir çocuk MOC yapmak yerine, ANA bir çocuk olun.

Bu. Her zaman BG otomatik olarak ANA itti alır kaydeder. Şimdi, ANA kurtarmak için arama ve sonra kurtaramadığım aramak için vardır, ama bu yaptığı tüm ana diske kaydeder kadar işaretçileri hareket.

Bu yöntemin güzelliği verileri düz uygulamalarınızı MOC (o zaman kurtulur geçer) arka plan MOK dan gider.

Varbazıiçin ceza geçişi, ama tüm ağır disk vurduğu ANA bitmiş olur. Ve eğer bu performBlock master kaydeder tekme, sonra ana konu sadece istek gönderir ve hemen döner.

Lütfen bana nasıl gidiyor bildirin!

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • edwin maldonado

    edwin maldon

    28 Mart 2009
  • Jaclyn W

    Jaclyn W

    5 Mayıs 2006
  • K-391

    K-391

    23 EKİM 2012