2011-10-20 25 views
12

Tôi có thể tạo đối tượng được quản lý mới bên trong ứng dụng của mình, trong chế độ xem riêng, tôi có chế độ xem bảng hiển thị tất cả các đối tượng tôi có.Làm mới dữ liệu NSFetchedResultsController?

Khi tôi tạo đối tượng được quản lý mới (trong chế độ xem hoàn toàn riêng biệt), tôi đang gửi thông báo đang cố gắng xem lại bảng bằng dữ liệu mới bao gồm đối tượng mới mà tôi vừa tạo.

Tôi không chỉnh sửa chế độ xem bảng.

Chỉ có một ngữ cảnh được quản lý.

Tôi không thể hiểu những gì tôi đang làm sai. Nếu tôi đóng ứng dụng và khởi chạy lại đối tượng mới của tôi là ở chế độ xem bảng. Tôi đang cố gắng gọi reloadData khi tôi nhận được thông báo một đối tượng mới đã được thực hiện và tôi cũng đã thử thực hiện tìm nạp lại, nhưng tất cả những gì tôi kết thúc là chế độ xem bảng trống.

Về mã, ListViewController tôi:

@interface MyNotesViewController : UIViewController 
{ 
    NSManagedObjectContext * __managedObjectContext; 
    UITableView * _notesTableView; 
    MyNotesTableViewDelegate_DataSource * _tableDelegate_DataSource; 
} 

My viewDidLoad trông như thế này:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    _tableDelegate_DataSource = [[MyNotesTableViewDelegate_DataSource alloc] init]; 
    _tableDelegate_DataSource.managedObjectContext = __managedObjectContext; 
    [_notesTableView setDataSource:_tableDelegate_DataSource]; 

    NSError * _coreDataError; 
    BOOL success = [[_tableDelegate_DataSource fetchedResultsController] performFetch:&_coreDataError]; 

    if(success){ 
     [_notesTableView reloadData]; 
    } 
} 

Trong đại biểu/đối tượng nguồn dữ liệu của tôi, tôi có: trích

@interface MyCommutesTableViewDelegate_DataSource : NSObject 

<UITableViewDataSource, NSFetchedResultsControllerDelegate> 
{ 
    NSManagedObjectContext * __managedObjectContext; 
    NSFetchedResultsController * __fetchedResultsController; 
} 

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext; 

@end 

Thực hiện :

-(NSFetchedResultsController*)fetchedResultsController{ 
    if(!__fetchedResultsController){ 
     NSFetchRequest * request = [[NSFetchRequest alloc] init]; 
     [request setEntity:[NSEntityDescription entityForName:@"Note" inManagedObjectContext:__managedObjectContext]]; 

     [request setFetchBatchSize:10]; 

     NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO]; 
     [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
     [sortDescriptor release]; 

     __fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:__managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 


     __fetchedResultsController.delegate = self; 
     [request release]; 

    } 
    return __fetchedResultsController; 
} 

tôi có phương pháp Stander UITableView nguồn dữ liệu ở đây:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 
    id <NSFetchedResultsSectionInfo> sectionInfo = 
    [[__fetchedResultsController sections] objectAtIndex:section]; 
    return [sectionInfo numberOfObjects]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"NotesTableViewCell"; 

    NotesTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) {   
     NSArray * topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NotesTableViewCell" owner:nil options:nil]; 
     for(id currentObject in topLevelObjects){ 
      if([currentObject isKindOfClass:[UITableViewCell class]]){ 
       cell = (NotesTableViewCell*) currentObject; 
       break; 
      } 
     } 

    } 

// Configure the cell. 
    Note * _note = [__fetchedResultsController objectAtIndexPath:indexPath]; 

    [...] 

    return cell; 
} 

CẬP NHẬT

tôi trở lại là chỉ đơn giản là yêu cầu tất cả các đối tượng vì tôi đã phải sửa chữa nhanh chóng vấn đề của tôi, và sau đó tôi nhận ra, sau khi Tôi lưu ngữ cảnh của tôi, yêu cầu tìm nạp của tôi trước đây tôi đã sử dụng khi khởi chạy ứng dụng, hiện không trả về dữ liệu, không có lỗi nhưng nó chỉ trả về không có gì.

Vì vậy, tôi đoán không có vấn đề với cách tôi đang triển khai NSFetchResultsController. Nhưng làm thế nào để yêu cầu bắt đầu không trả lại kết quả sau khi tôi lưu một đối tượng mới?

Lưu ý Tôi vẫn nhận được tất cả các đối tượng của mình nếu tôi khởi chạy lại, bao gồm cả đối tượng mới thêm.

tiêu chuẩn yêu cầu:

-(NSArray*)getNotes{ 
    NSFetchRequest * request = [[NSFetchRequest alloc] init]; 

    NSEntityDescription * entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:[self managedObjectContext]]; 
    [request setEntity:entity]; 

    NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO]; 
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
    [sortDescriptor release]; 

    NSError * coreDataError; 
    NSArray * fetchedObjects = [[self managedObjectContext] executeFetchRequest:request error:&coreDataError]; 
    [request release]; 

    if(fetchedObjects != nil){ 
     return fetchedObjects; 
    } else { 
     NSLog(@"ERR: %@", coreDataError); 
     return nil; 
    } 
} 

Tôi đang chờ đợi một thông báo nói với tôi một đối tượng mới đã được thêm vào Core Data, và sau đó tôi kêu gọi các phương pháp trên và sau đó gọi reloadData trên tableview của tôi ...

Trả lời

26

Bạn đang đặt UITableViewController làm NSFetchedResultsControllerDelegate. Tốt lắm. Bây giờ cố gắng thực hiện các phương pháp controllerDidChangeContent: trong TableViewController như vậy:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    [self.tableView reloadData]; 
} 

NSFetchedResultsController của bạn sẽ lắng nghe đối tượng bị loại bỏ hoặc mới trong Core dữ liệu và thông báo cho đại biểu của nó (TableViewController của bạn) thay đổi. Kiểm tra dự án mẫu dữ liệu cốt lõi trong Xcode để thực hiện điều này tốt hơn nữa với các hoạt ảnh thêm và loại bỏ trong UITableView.

+0

tất nhiên bạn sẽ muốn tải lại _notesTableView trong trường hợp của bạn. – huesforalice

+10

Cũng đừng quên rằng 'NSFetchedResultsController' sẽ chỉ phản ứng với' -save: 'được gọi trên' NSManagedObjectContext'. Vì vậy, bạn có thể không thấy phương thức này kích hoạt nếu bạn không lưu thực thể mới được tạo ra. –

+0

Cảm ơn, tôi đang thực hiện controllerDidChangeContent: từ giao thức NSFetchedResultsControllerDelegate, gọi reloadData trên tableview của tôi. Tôi đã thêm điểm ngắt và phương thức này đang được gọi, nhưng chế độ xem bảng đang tải lại trống. Nếu tôi khởi chạy lại ứng dụng, tôi có thể xem tất cả hồ sơ của mình bao gồm cả bản ghi mới. Tôi đang thiếu gì? PS: tôi có phải thực hiện điều khiển: didChangeObject: atIndexPath: forChangeType: newIndexPath? – Daniel

2

Hãy chắc chắn để thêm phương pháp didChangeObject:

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeObject:(id) anObject 
     atIndexPath:(NSIndexPath *)indexPath 
    forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    switch(type) 
    { 
    case NSFetchedResultsChangeInsert: 
     [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeDelete: 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    case NSFetchedResultsChangeUpdate: 
     [self configureCell:[self.tableView 
    cellForRowAtIndexPath:indexPath] 
       atIndexPath:indexPath]; 
     break; 
    case NSFetchedResultsChangeMove: 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     [self.tableView insertRowsAtIndexPaths:[NSArray 
          arrayWithObject:newIndexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
    } 
} 

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObject *note = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.textLabel.text = [note valueForKey:@"title"]; 
} 

Đối tượng quản lý mới xuất hiện trong giao diện bảng sau này.

0

Trong trường hợp ai đó gặp vấn đề tương tự, như tôi đã có nó. Tôi đã thử các giải pháp trên với đánh dấu màu xanh lá cây, nhưng nó sẽ không làm việc cho tôi. Tôi đã theo dõi Apple's code và mọi thứ đều ổn.

đơn giản, chỉ cần thực hiện ba "Fetchcontroller" chức năng đại biểu

func controllerWillChangeContent(controller: NSFetchedResultsController) { 
      self.tableView.beginUpdates() 
     } 


    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { 

      switch type { 
      case .Insert: 
       self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) 
      case .Delete: 
       self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
      case .Update: 
       print("") 
       self.configureCell(self.tableView.cellForRowAtIndexPath(indexPath!)!, indexPath: indexPath!) 
      case .Move: 
       self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
       self.tableView.insertRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 
      } 
     } 


func controllerDidChangeContent(controller: NSFetchedResultsController) { 
      self.tableView.endUpdates() 
     } 
Các vấn đề liên quan