17

Chúng tôi đã cố gắng gỡ lỗi một vấn đề đa ngữ cảnh/luồng dữ liệu lõi trong đó hợp nhất thông báo lưu dữ liệu lõi vào chủ đề chính NSManagedObjectContext của chúng tôi là gián đoạn ứng dụng. Điều này đang giảm ~ 2% số phiên ứng dụng của chúng tôi và chúng tôi đang thua lỗ về cách giải quyết vấn đề này. Chúng tôi thực sự đánh giá cao bất kỳ hướng dẫn hoặc lời khuyên chung nào về những gì có thể gây ra sự cố này.EXC_BAD_ACCESS khi hợp nhấtThay đổiFromContextDidSaveNotification

Chúng tôi có một thiết lập Core Data trông như thế này:

Core Data Stack N.B. Đây là mặc định ngăn xếp Core Data trong Magical Ghi v2.3 tạo từ [MagicalRecord setupAutoMigratingCoreDataStack]

Đây là kịch bản mà ứng dụng của chúng tôi là đâm:

  1. yêu cầu HTTP trả về JSON
  2. JSON được phân tách vào NSManagedObject s (một số thực thể mới, một số đơn vị cập nhật) trên gốc Saving Context
  3. gốc Saving Context tiết kiệm đến cửa hàng khăng khăng
  4. NSManagedObjectContextDidSaveNotification được phát bởi Dữ liệu cốt lõi. Ngữ cảnh mặc định trên hàng đợi chính quan sát điều này và gọi mergeChangesFromContextDidSaveNotification: với các thay đổi về chủ đề chính của NSDictionary.
  5. Lỗi treo khi objectID được gửi tới một đối tượng không hợp lệ (rất có thể là NSManagedObject đã được deallocated).

này đang xảy ra bên trong việc thực hiện riêng của NSManagedObjectContextmergeChangesFromContextDidSaveNotification: vì vậy không thể cho chúng tôi để xem những gì đã thực sự đi sai ở đây; tất cả những gì chúng ta có thể nói tại thời điểm này là một vật thể nên tồn tại, thì không.

enter image description here

này chỉ xảy ra trên một phần trăm nhỏ của Core dữ liệu tiết kiệm, chỉ ra rằng có thể không phải là một lỗi cơ bản trong Core Data → API chồng của chúng tôi. Hơn nữa, không có dấu hiệu cho thấy kích thước hoặc loại thay đổi (chèn/cập nhật/xóa) trong bối cảnh thay đổi có ảnh hưởng đến khả năng xảy ra sự cố.

+1

Loại MOC nào đồng thời sử dụng? Và bạn đang sử dụng 'performBlock:' hoặc 'performBlockAndWait:' khi hợp nhất các thay đổi? –

+0

MoC mặc định sử dụng loại đồng thời hàng đợi chính và MoC lưu gốc sử dụng loại đồng thời hàng đợi riêng tư. Bất kỳ sự tương tác nào với bất kỳ hàng đợi riêng nào trong ứng dụng đều sử dụng performBlock hoặc performBlockAndWait. Theo Tài liệu của Apple, chúng tôi không tương tác với bối cảnh Mặc định thông qua khối thực hiện, tuy nhiên chúng tôi đảm bảo rằng chúng tôi không bao giờ tương tác với nó khi chúng tôi không nằm trong chuỗi chính. – JConway

+4

Chỉ cần 2ct của tôi; Tôi đã có một vấn đề như vậy một lần trong khi làm tất cả mọi thứ bởi cuốn sách, và nó được gây ra bởi một 'NSLog()' của đối tượng 'NSNotification' (hoặc thuộc tính' userInfo' của nó). Kể từ đó, tôi chỉ làm 'mergeChangesFromContextDidSaveNotification:' ngay lập tức theo sau là 'save' trên ngữ cảnh, không chạm vào thông báo theo bất kỳ cách nào khác. Kể từ đó tôi chưa bao giờ thấy nó segfault một lần nữa. – mvds

Trả lời

1

Đã lâu rồi kể từ khi câu hỏi này được đăng và sau khi khám phá lại, tôi muốn trả lời câu hỏi của riêng mình vì lợi ích của những người khác tìm thấy chuỗi này.

Trong trường hợp của tôi, tôi đã di chuyển một cơ sở mã lớn từ anh chị em NSManagedObjectContexts được cập nhật qua số NSManagedObjectContextDidSaveNotification. Tuy nhiên, vấn đề không thực sự liên quan đến điều này, mặc dù điều này đã làm lộ ra vấn đề.

Nguyên nhân thực sự của việc này là những nơi có phần cũ hơn của mã, do các kỹ sư trước đó thiết lập, đã thiết lập KVO trên NSManagedObject và các thuộc tính của chúng. Nó transpired rằng KVO trên thực thể Core Data là trong thực tế, một ý tưởng rất xấu.

Chính xác hơn, có vẻ như điều này xảy ra khi KVO được thiết lập trên thực thể và đối tượng hoặc mục tiêu của mối quan hệ trên đối tượng này đã bị xóa khỏi NSPersistentStore. Điều kiện thứ hai này dường như không phải là số chỉ có nguyên nhân của vấn đề, nhưng chắc chắn là nguyên nhân rất nổi bật trong tình huống của tôi.

Lesson đã học:

  1. Sử dụng kết quả lấy điều khiển khi bạn cần. KVO không phải là một phím tắt thuận tiện và bạn không nên tránh di chuyển mã KVO lõi dữ liệu tinh vi để NSFetchedResultsControllers hoặc một lựa chọn hợp lý khác như sự trì hoãn sẽ chỉ làm tổn thương bạn.
  2. Dữ liệu cốt lõi đa luồng là một kỹ năng khó khăn nhưng rất đáng giá để trở thành một chuyên gia. Hiểu biết về Ngăn xếp dữ liệu cốt lõi của bạn và các sắc thái và hạn chế của Đa luồng dữ liệu lõi là hoàn toàn đáng giá.
4

Các tài liệu của NSManagedObjectContextDidSaveNotification nói rằng:

"Bạn có thể vượt qua các đối tượng thông báo cho mergeChangesFromContextDidSaveNotification: trên thread khác, tuy nhiên bạn không phải sử dụng các đối tượng quản lý trong từ điển thông tin người dùng trực tiếp trên thread khác Để biết thêm chi tiết,. xem Đồng thời với dữ liệu cốt lõi trong Hướng dẫn lập trình dữ liệu cốt lõi. "

Có thể đây là vấn đề? Tôi sẽ đảm bảo rằng đối tượng mà bạn nhận được từ thông báo sẽ được lưu trên Default Context trên cùng một luồng mà nó đã được đăng bởi Root.

+0

Đây chính là vấn đề của tôi. Tôi quên gửi đi bằng cách gọi 'performBlock' trên ManagedObjectContext. – TMob

2

Một khả năng là cửa hàng liên tục của bạn đã bị hỏng và ở trạng thái không nhất quán. Nếu điều này xảy ra một mã lỗi được tạo ra mà Magical Record không nhất thiết phải đối phó với. Đây có thể là nguồn gốc của một số sự cố ngẫu nhiên khó lặp lại liên quan đến Bản ghi Magical (và có thể hoặc không thể được coi là lỗi Bản ghi Magical).

Cần đọc các chủ đề về Bản ghi Magical here (cùng một vấn đề) và here (vấn đề khác nhau, nhưng có thể là nguyên nhân tương tự). Khi tôi gặp những vấn đề này, tôi đã thực hiện một số bản sửa lỗi tạm thời theo các gợi ý khác nhau trong các chủ đề đó, nhưng cuối cùng tôi quyết định loại bỏ sự phụ thuộc vào Magical Record, và tôi đã không có vấn đề gì kể từ đó.

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