8

Tôi có một số UITableView (với các ô tùy chỉnh, nếu có vấn đề) được nối với một số NSFetchedResultsController. Ứng dụng của tôi cũng sử dụng thông báo đẩy. Khi một thông báo từ xa đến, tôi cập nhật (core) mô hình dữ liệu của tôi trong hai giai đoạn:NSFetchedResultsController delay nhất quán trong việc cập nhật ô UITableView; chèn tác phẩm ngay lập tức

1) Nhận danh hiệu (với một số dữ liệu tùy chỉnh) và lưu nó như là một dữ liệu cốt lõi mới Entity. Ở đây tôi gọi NSManagedObjectContext save(). NSFetchedResultsController chọn phần chèn và kích hoạt phương thức ủy quyền của nó didChangeObject với NSFetchedResultsChangeType = NSFetchedResultsChangeInsert. Các tableview được cập nhật ngay lập tức. (Một hàng mới được chèn)

2) Tải xuống nội dung khác liên quan đến ô qua NSURLSession chèn nội dung vào số Entity ở trên và gọi lại save() method. NSFetchedResultsController lại chọn bản cập nhật và kích hoạt phương thức ủy quyền của nó didChangeObject với NSFetchedResultsChangeType = NSFetchedResultsChangeUpdate. Đây là nơi tôi gọi phương thức configureCell của mình. TableView được cập nhật nhưng với độ trễ nhất quán khoảng 10 giây.

Ở cả hai giai đoạn (bảng sao lưu tải xuống bối cảnh tải xuống ngữ cảnh) dữ liệu cần được hiển thị đã được lưu giữ bởi dữ liệu cốt lõi. (Đối với ví dụ bên trong phương pháp configureCell.. của tôi, tôi biết tôi không thiết lập bất kỳ nhãn tế bào để nil hay như vậy

phương pháp NSFetchedResultsController đại biểu của tôi:.

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
[self.mainTableView beginUpdates]; 
} 

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


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
UITableView *tableView = self.mainTableView; 

switch(type) { 

    case NSFetchedResultsChangeInsert: 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeUpdate: 
     [self configureCell:(MessageTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
    } 
} 

Những điều khác mà tôi đã cố gắng bên case NSFetchedResultsChangeUpdate:

  1. Cố gắng gọi processPendingChanges trước bối cảnh save
  2. gọi reloadRowsAtIndexPaths thay vì gọi configureCell trực tiếp
  3. Cố gắng gói cập nhật .. phương pháp bên beginUpdatesendUpdates (mặc dù tôi đã có một cặp mà nên thực hiện công việc)
  4. [tableView reloadData]
  5. numberOfRowsInSection không phải là 0!
  6. NSFetchedResultsController phương thức ủy quyền chỉ chạy trên chuỗi chính.

Tóm lại, tất cả (?) Phương pháp đại biểu phù hợp được gọi chính xác. Tuy nhiên, tôi thấy sự chậm trễ nhất quán ~ 10 giây khi cập nhật một ô. Tuy nhiên, việc chèn xảy ra gần như ngay lập tức. Bất kỳ ý tưởng?

+0

Bạn không hiển thị mã nơi bạn cập nhật bảng sau khi thao tác mạng hoàn tất nhưng tôi cho rằng bạn không gửi bản cập nhật trên hàng đợi chính. – Paulw11

+0

Vâng, nếu bằng cách "gửi đi" bản cập nhật, bạn có nghĩa là gọi 'save', thì không, tôi đang gọi' save' từ phương thức ủy nhiệm 'NSURLSession'' URLSession: downloadTask: didFinishDownloadingToURL: 'KHÔNG nằm trên chuỗi chính nếu tôi không nhầm? –

+0

Vì vậy, bạn đang sử dụng ngữ cảnh luồng nền mà bạn đã tạo và lưu thay đổi lên? – Wain

Trả lời

4

Nhận xét của @ Paulw11 về dispatch_async... đặt tôi đi đúng hướng. Vấn đề nằm trong thực tế là tôi đã được sử dụng cùng một đối tượng ManagedObjectContext trong hai chủ đề khác nhau mặc dù họ không đồng thời truy cập nó cùng một lúc. Ngay sau khi tôi gửi các cuộc gọi save của tôi (đã được trên một sợi nền) trên hàng đợi chính (bằng cách gói nó bên trong dispatch_async(dispatch_get_main_queue,^{ UIUpdate code here });), sự chậm trễ biến mất. Một lời giải thích có thể là gọi số save trên một kết quả chủ đề nền trong các phương thức ủy nhiệm được gọi trên luồng nền.

Dù sao, quay lại giải pháp - không bao giờ chia sẻ cùng một đối tượng ManagedObjectContext giữa nhiều chuỗi. Use parent/child context relationships nếu bạn đang cập nhật ngày lõi trong nhiều hơn một chuỗi.NSFetchedResultsController cũng phát độc đáo với mẫu này.

Các vấn đề liên quan