2012-09-14 16 views
8

güncellemesinden sonra getirilen değerleri yeni ekler/kaldırmaz. Benzer sorulardan sonra, şu ifadeyle başlamak istiyorum: "NSFetchedResultsController delegesini ayarlamıştım, işe yaramadı." .NSFetchedResultsController,

Bu yüzden hücreleri NSFetchedResultsController ile doldurulmuş basit bir TableViewController var. Ayrıca NSFetchedResultsController temsilci yöntemleri bazı ayıklama etiketlerle uygulayan

@property (strong, nonatomic) NSFetchedResultsController *frc; 

... 

- (NSFetchedResultsController *)frc 
{ 
    if (!_frc) 
    { 
     NSError *error = nil; 
     NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:e_product]; 
     request.sortDescriptors = [NSArray arrayWithObjects: 
           [NSSortDescriptor sortDescriptorWithKey:@"product_group.product_group_name" ascending:YES], 
           [NSSortDescriptor sortDescriptorWithKey:f_product_name ascending:YES], 
           nil]; 
     _frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[DTGGlobalSettings sharedInstance].moc sectionNameKeyPath:@"product_group.product_group_name" cacheName:nil]; 
     _frc.delegate = self; 
     [_frc performFetch:&error]; 
     if (error) 
     { 
      NSLog(@"Error while fetching products: %@!", error.userInfo); 
     } 
    } 

    return _frc; 
} 

: Burada FRC init kod ben yenile düğmesine sahip benim NavigationBar yılında

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates. 
    NSLog(@"controllerWillChangeContent"); 
    [self.tableView beginUpdates]; 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 

    UITableView *tableView = self.tableView; 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     NSLog(@"didChangeObject - insert"); 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     NSLog(@"didChangeObject - delete"); 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     NSLog(@"didChangeObject - update"); 
     [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
     break; 

    case NSFetchedResultsChangeMove: 
     NSLog(@"didChangeObject - move"); 
     [tableView deleteRowsAtIndexPaths:[NSArray 
              arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray 
              arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     NSLog(@"didChangeSection - insert"); 
     [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeDelete: 
     NSLog(@"didChangeSection - delete"); 
     [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
// The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
NSLog(@"controllerDidChangeContent"); 
[self.tableView endUpdates]; 
} 

, işlevi ürün kataloğunu ateşlemek için Aşağıdakileri yapan yöntem: 1. Uzak MySQL sunucusundan ürünler getiriliyor 2. Kimliği olan ürün mevcut değilse - oluşturur ve tüm alanları doldurur 3. Varsa, tüm alanlar, tüm alanlara göre güncelleştirilir. getirilen değerler

2. ve 3. sıradan sonra mağaza kaydedilir. Uygulamadaki tüm CoreData işlemlerinde tek bir NSManagedObjectContext kullanıyorum.

Uygulamayı ilk kez başlattığımda, henüz getirilmeyen ürün olmadığından TVC boş. Yenile'ye bastığımda, yeni ürünler ManagedObjectContext'e getirilir ve eklenir, ancak NSManagedObjectContext herhangi bir değişiklik görmez/duymaz: delege yöntemleri çağrılmaz, bu nedenle TVC'ye yeni satır eklenmez. Uygulamayı yeniden başlattığımda, yeni ürünler TVC'ye hiçbir sorun olmadan getiriliyor.

Orada bazı ürünler olduğunda yenileme düğmesine bir kez daha basarsam, kısa bir süre sonra hepsi kaybolur. Bazı hata ayıklama, varlıkların alanlarını güncelleştirdikten sonra gerçekleşirse (aslında değerler aynıdır) ve mağazayı kaydederken bana gösterdi. Temsilci yöntemleri bu kez bir çekicilik ve her güncelleştirilmiş ve kaydedilen varlık denetleyicisi için çalışır: didChangeObject: atIndexPath: forChangeType: newIndexPath forChangeType = NSFetchedResultsChangeDelete ile çağrılır.

Soru # 1: Neden NSFetchedResultsController uygulama yeniden başlatılmadan eklenen varlıkları göremiyor? Soru # 2: Neden NSFetchedResultsController işaretleri zaten var olmayan "var olmayan" (?) Işaretler ve mağaza kaydettikten sonra bunları TVC'den kaldırır?

ben olmanın bütün Geçen hafta bu konuyla mücadele herhangi bir yardım ve fikir takdir ediyorum

; (() Jody için

UPD1: İşte bazı ayrıntılar bazı değişkenler paylaşmak için özel sınıf DTGGlobalSettings kullanmak vardır. . nedense onay kutusu "Kullanım CoreData" yeni oluşturarak görmüyorum çünkü

+(DTGGlobalSettings *)sharedInstance 
{ 
    static DTGGlobalSettings *myInstance = nil; 

    if (nil == myInstance) 
    { 
     myInstance = [[[self class] alloc] init]; 
     // set values here 
     // try to acces MOC to init CoreData 
     [myInstance moc];   
     myInstance.baseURL = @"http://local.app/"; 
} 
return myInstance; 
} 

, Apple belgelerine bir örnek kullanılan CoreData yığınını init için: app genelinde Ben onun sharedInstance özelliğini init nasıl Xc'de daha önce gördüğümden eminim gazel, ama şimdi yok; ((Xcode 4.4.1): Ben CoreData erişmesi gereken yere

#pragma mark Core Data stack 

- (NSManagedObjectContext *) moc { 

if (_moc != nil) { 
    return _moc; 
} 
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
if (coordinator != nil) { 
    _moc = [[NSManagedObjectContext alloc] init]; 
    [_moc setPersistentStoreCoordinator: coordinator]; 
} 
return _moc; 
} 


- (NSManagedObjectModel *)managedObjectModel { 

if (_managedObjectModel != nil) { 
    return _managedObjectModel; 
} 
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];  
return _managedObjectModel; 
} 


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 

if (_persistentStoreCoordinator != nil) { 
    return _persistentStoreCoordinator; 
} 
NSURL *storeUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
storeUrl = [storeUrl URLByAppendingPathComponent:DOC_NAME]; 

NSError *error; 
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; 

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) { 
    NSLog(@"Error adding a store to the coordinator: %@, %@", error, error.userInfo); 
}   
return _persistentStoreCoordinator; 
} 

-(void)saveDataStore 
{ 
    NSError *error; 
    if (![self.moc save:&error]) NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
} 

DTGGlobalSettings ait 'moc' (ManagedObjectContext) özelliği ardından uygulamanın her yerde kullanılır.

Şimdi ikinci bölüme, veritabanını güncelleştirin.JSON biçiminde uzak web sunucusundan bazı yeni varlıklar alıyorum, sonuçta ortaya çıkan sözlüğü gidiyorum ve istek sonuçlarında bulunan her varlık için createFromDictionary yöntemini çağırıyorum. İşte kod: Ben fethed varlıkların bittiğinde

+(Product *)createFromDictionary:(NSDictionary *)entityData inContext:(NSManagedObjectContext *)moc performUpdate:(BOOL)update 
{ 
Product *result; 
if (update) 
{ 
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:e_product]; 
    request.predicate = [NSPredicate predicateWithFormat:@"%K = %@", f_product_id, [entityData objectForKey:f_product_id]]; 
    result = [[DTGGlobalSettings sharedInstance].moc executeFetchRequest:request error:nil].lastObject; 
    if (!result) 
    { 
     NSLog(@"Error updating Product ID %@! Cannot fetch entity.", [entityData objectForKey:f_product_id]); 
     return nil; 
    } 
} else 
{ 
    result = [NSEntityDescription insertNewObjectForEntityForName:e_product inManagedObjectContext:[DTGGlobalSettings sharedInstance].moc]; 
} 

result.product_id = [[DTGGlobalSettings sharedInstance].numFormatter numberFromString:[entityData objectForKey:f_product_id]]; 
result.product_image = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[DTGGlobalSettings sharedInstance].baseURL stringByAppendingString:[entityData objectForKey:f_product_image]]]]; 
result.product_name = [entityData objectForKey:f_product_name]; 

return result; 
} 

, ben [[DTGGlobalSettings sharedInstance] saveDataStore] (yukarıya bakınız) diyoruz. Bu noktada, TVC'deki mevcut satırlar (eğer varsa) ortadan kayboldu. Bazı yeni varlıklar ekliyor olsaydım, hiçbir şey olmayınca, yani TVC satırlarını güncellemez.

+0

Yanlış kod gönderdiniz. İlginç bitler, verileri veritabanınıza nasıl aktaracağınız ve hem içe aktarma hem de getirilen sonuç denetleyicisi için temel veri kümesini nasıl ayarlayacağınızdır. –

+0

UPD1'de sorduğunuz bazı ayrıntıları ekledim. Umarım artık bununla ilgili olarak ... – Arseniy

+0

güncellemeyle ilgili ne düşündüğüm daha net? – Arseniy

cevap

14

Aslında, ilk düzenleme işleminin gerekli tüm bilgileri aldığını düşünüyorum. Sadece okumamıştım (uzun bir kod satırını okuyarak ilerlemeyi sevmem ve bazen yapmama gerek yok - benim kötüyüm).

Sorununuz, FRC sıralama tanımlayıcılarınızla ilgili görünüyor. FRC, ilişki sıralama tanımlayıcılarını çok iyi güncellemeyi sürdürmekle iyi bir şekilde ilgilenmemektedir.

Bazıları bunun nasıl tasarlandığını tartıştı. Bunun bir hata olduğunu düşünüyorum.

Bu iletiyi al benim için Changing a managed object property doesn't trigger NSFetchedResultsController to update the table view. Umarım, davayla benzerlikleri göreceksin.

+0

Bu harika! Sadece sıralı tanımlayıcıları ve bölüm adı yolunu kaldırdım ve işe yaradı! Bunun böyle çalıştığını asla tahmin edemem;) Teşekkürler! – Arseniy

+0

bu sorun hala var mı? –

+0

Evet. https://insanitysauce.files.wordpress.com/2013/09/bsxgx3vciaax5g5.jpg –

1

Ben de aynı sorunu ile vakit geçirdi ve şu öğrendim: nesneleri eklerken sectionNameKeyPathnil değerini alabilir bir ilişki alanına atıfta bulundu zaman, FRC güncelleme işe yaramaz.

Bu, Xcode konsolunda, ilgili alanın nil olarak ayarlandığı nesneler için oluşturulacağını belirten bir uyarı ile ilgili olabilir. Sanırım bu bölüm FRC'nin iç işleriyle uğraşıyor.