2010-03-17 40 views
57

Tôi có một NSManagedObjectContext, trong đó tôi có một số lớp con của NSManagedObjects sao cho một số là các vùng chứa cho những người khác. Những gì tôi muốn làm là xem một đối tượng cấp cao nhất để được thông báo về bất kỳ thay đổi nào đối với bất kỳ thuộc tính, liên kết hoặc thuộc tính/liên kết nào của bất kỳ đối tượng nào chứa nó.Làm thế nào tôi có thể theo dõi/quan sát tất cả các thay đổi trong một biểu đồ con?

Sử dụng 'hasChanges' của bối cảnh không cung cấp cho tôi mức độ chi tiết đầy đủ. Phương thức 'isUpdated' của đối tượng chỉ áp dụng cho đối tượng đã cho (và không phải bất kỳ thứ gì trong các liên kết của nó). Có một thuận tiện (có lẽ, dựa trên KVO) là tôi có thể quan sát những thay đổi trong một bối cảnh được giới hạn trong một đồ thị con?

Trả lời

129

Bạn sẽ muốn nghe số NSManagedObjectContextObjectsDidChangeNotification để nhận tất cả các thay đổi đối với mô hình dữ liệu của mình. Điều này có thể được thực hiện bằng mã như sau:

[[NSNotificationCenter defaultCenter] 
     addObserver:self 
     selector:@selector(handleDataModelChange:) 
      name:NSManagedObjectContextObjectsDidChangeNotification 
      object:myManagedObjectContext]; 

mà sẽ kích hoạt -handleDataModelChange: trên bất kỳ thay đổi đối với myManagedObjectContext ngữ cảnh.

-handleModelDataChange của bạn: Phương pháp sẽ giống như thế này:

- (void)handleDataModelChange:(NSNotification *)note 
{ 
    NSSet *updatedObjects = [[note userInfo] objectForKey:NSUpdatedObjectsKey]; 
    NSSet *deletedObjects = [[note userInfo] objectForKey:NSDeletedObjectsKey]; 
    NSSet *insertedObjects = [[note userInfo] objectForKey:NSInsertedObjectsKey]; 

    // Do something in response to this 
} 

Như bạn có thể thấy, thông báo chứa thông tin mà trên đó được quản lý đối tượng đã được cập nhật, xóa, và chèn vào. Từ thông tin đó, bạn sẽ có thể hành động để đáp ứng với những thay đổi về mô hình dữ liệu của bạn.

+0

Cảm ơn! Tôi không biết thông báo đó. Nó vẫn có vẻ như quá mức cần thiết để thực hiện tìm kiếm mỗi khi thông báo được gửi đi. Điều đó nói rằng, tôi không chắc làm thế nào nó có thể được tối ưu hóa ngay cả bởi Apple; về cơ bản, nó vẫn là một đồ thị truyền tải. –

+4

Nếu bạn sử dụng NSPredicate để lọc qua các đối tượng này, nó thực sự khá hiệu quả vì mọi thứ đều nằm trong bộ nhớ. Tôi sử dụng giải pháp này trong một số ứng dụng cho iPhone và vẫn chưa có một nút cổ chai hiệu suất trong lĩnh vực này. –

+0

Ah, hãy gọi điện bằng cách sử dụng NSPredicate. Đã không nghĩ về điều đó. –

19

đây là một ví dụ đơn giản trong Swift:

NotificationCenter.default.addObserver(forName: .NSManagedObjectContextObjectsDidChange, object: nil, queue: nil) { note in 
     if let updated = note.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>, updated.count > 0 { 
      print("updated: \(updated)") 
     } 

     if let deleted = note.userInfo?[NSDeletedObjectsKey] as? Set<NSManagedObject>, deleted.count > 0 { 
      print("deleted: \(deleted)") 
     } 

     if let inserted = note.userInfo?[NSInsertedObjectsKey] as? Set<NSManagedObject>, inserted.count > 0 { 
      print("inserted: \(inserted)") 
     } 
    } 
+3

Thông thường người ta cần phải theo dõi giá trị trả về 'hãy quan sát = NSNotificationCenter.defaultCenter(). AddObserverForName (..) {..}' để có thể ngừng quan sát bằng cách gọi 'NSNotificationCenter.defaultCenter(). RemoveObserver (quan sát) '. –

+1

@DanBeaulieu, nếu bạn đã sử dụng phiên bản dựa trên bị chặn, 'NSNotificationCenter.defaultCenter(). AddObserverForName (..) {‌ ..}', bạn cần giữ lại quan sát được trả về. –

+0

@LevLandau Tôi sẽ hoàn tác chỉnh sửa và đọc, cảm ơn vì đã thông báo –

0

đối với tôi nó chỉ mất sau hai func, có lẽ điều này tiết kiệm giờ đối với một ai đó

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

func controllerDidChangeContent(controller: NSFetchedResultsController) { 
    tableView.endUpdates() 
} 
+2

Điều này không liên quan gì đến câu hỏi này. – rmaddy

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