2013-10-22 58 views
1

我對Core Data很新穎。NSManagedObjectContext看不到實體屬性的變化

我的數據模型有一個User實體,它具有從服務器獲取的屬性fullName。我使用NSFetchedResultsController在表格視圖中顯示所有Users的列表。由於所有Users都獲得了其更新的fullName屬性,我希望MOC發送更改通知。但是,這不是那樣做的。因此,我的FRC也沒有更新。

我已經清理並構建,修改了我的數據模型並構建,甚至刪除了User.h/m並重新生成了它。但我仍然無法弄清楚問題所在。並且fullName實際上正在更新,我可以手動重新加載表視圖並查看更改。我的問題是什麼?

代碼:

設置fullName

- (BOOL)methodName:(NSDictionary *)data 
{ 
    self.fullName = data[@"fullName"]; 
    self.imageData = data[@"image"]; 
} 

表視圖:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
return [self.frc.sections[section] numberOfObjects]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
static NSString *CellIdentifier = @"cell"; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 
[self configureCell:cell atIndexPath:indexPath]; 

return cell; 
} 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{ 
User *user = [self.frc objectAtIndexPath:indexPath]; 

cell.imageView.image = [UIImage imageWithData:user.imageData]; 
cell.textLabel.text = user.fullName; 
} 

設置FRC:

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

if (!self.model) self.model = [XPModel sharedInstance]; 
[self.model addDelegate:self]; 

if (!self.frc) { 
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([User class])]; 
    request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"fullName" ascending:YES]]; 
    request.fetchBatchSize = 10; 

    self.frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.model.moc sectionNameKeyPath:nil cacheName:nil]; 
    self.frc.delegate = self; 
} 

NSError *error; 
[self.frc performFetch:&error]; 

NSAssert(!error, error.localizedDescription); 
} 

FRC委託方法:

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

UITableView *tableView = self.tableView; 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; // Only this is called, and only at the beginning 
     break; 

    case NSFetchedResultsChangeDelete: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; // Never called 
     break; 

    case NSFetchedResultsChangeMove: 
     [tableView deleteRowsAtIndexPaths:[NSArray 
              arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray 
              arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 
} 

建立模型:

- (void)coreDataSetup 
{ 
NSError *error; 

NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].lastObject URLByAppendingPathComponent:@"userdb.sqlite"];; 
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]; 

NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 

NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom]; 
NSAssert([storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error], error.localizedDescription) 

self.moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
self.moc.persistentStoreCoordinator = storeCoordinator; 
} 
+0

你實現了'controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:'?如果是這樣,你可以展示它嗎? –

+1

...並設置FRC代表? –

+0

@ArkadiuszHolko是的,我從蘋果的示例代碼複製它,所以沒有改變。它沒有被調用。 – duci9y

回答

1

從這個委託回調的文檔:

這種方法可以更新事件過程中調用多次(比如,如果你正在後臺線程中導入數據並將其添加到批處理中的上下文中)。您應該仔細考慮是否要在收到每封郵件時更新表格視圖。

我建議你不要依賴這種機制。在導入期間禁用委託會更好。一旦完成(或定期根據批量),只需保存並重新加載表格。

我沒有看到您保存在任何地方 - 您應該在導入大量數據時定期執行此操作。

+0

謝謝...這就是我最終做的。我從服務器收到最後一個用戶數據包後重新加載表視圖,同時在表視圖上顯示活動指示符。我的應用程序會每30秒檢查一次上下文是否有任何更改,如果有更改,則會進行保存。它也可以每3分鐘保存一次背景。 – duci9y

+1

也許使用'... didSaveNotication'會更好。無論何時保存一批,您都可以更新界面。 – Mundi