Để yêu cầu câu hỏi của tôi một cách hiệu quả, trước tiên hãy xem xét các kịch bản chính xác tôi đang phải đối mặt:Làm cách nào để đảm bảo các mục nhập duy nhất trong kho dữ liệu Core trong vùng chứa ứng dụng được chia sẻ được cả ứng dụng máy chủ lưu trữ và tiện ích mở rộng sử dụng?
Cài đặt chung
- Một loạt iOS 8 ứng dụng.
- Một hoặc nhiều tiện ích mở rộng iOS 8 (WatchKit, Share, v.v.) đi kèm với ứng dụng máy chủ lưu trữ.
- Ứng dụng máy chủ lưu trữ và tất cả tiện ích mở rộng đều chia sẻ cùng một kho lưu trữ SQLite lõi dữ liệu trong vùng chứa nhóm ứng dụng được chia sẻ.
- Mỗi ứng dụng/tiện ích mở rộng có NSPersistentStoreCoordinator và NSManagedObjectContext của riêng nó.
- Mỗi điều phối viên lưu trữ liên tục sử dụng một cửa hàng liên tục chia sẻ cùng một tài nguyên SQLite trong nhóm chứa như tất cả các cửa hàng liên tục khác.
- Ứng dụng và tất cả các tiện ích mở rộng sử dụng một codebase chung để đồng bộ hóa nội dung từ tài nguyên API từ xa trên Internet.
Chuỗi các sự kiện dẫn đến các vấn đề
Người dùng khởi chạy ứng dụng máy chủ. Nó bắt đầu tìm nạp dữ liệu từ tài nguyên API từ xa. Các đối tượng mô hình dữ liệu cốt lõi được tạo dựa trên phản hồi API và "upserted" vào bối cảnh đối tượng được quản lý của ứng dụng máy chủ lưu trữ. Mỗi thực thể API có một uniqueID xác định nó trong backend API từ xa. Bởi "upsert", tôi có nghĩa là đối với mỗi thực thể API, ứng dụng máy chủ chỉ tạo mục nhập mới trong Dữ liệu chính nếu không tìm thấy mục nhập hiện tại cho một uniqueID đã cho.
Trong khi đó, người dùng cũng khởi chạy một trong các tiện ích của ứng dụng máy chủ lưu trữ. Nó cũng thực hiện một số loại tìm nạp từ cùng một API từ xa. Nó cũng cố gắng để thực hiện một "upsert" khi phân tích cú pháp các phản ứng API.
Vấn đề: Điều gì sẽ xảy ra nếu cả ứng dụng máy chủ và tiện ích mở rộng cố gắng nâng cấp dữ liệu lõi cho cùng một thực thể API cùng một lúc? Để xem cách này có thể xảy ra, chúng ta hãy nhìn vào chuỗi các sự kiện cho một upsert:
Core Data Upsert trình tự:
- Mã API phân tích phân tích các UNIQUEID cho một API cho thực thể.
- Trình phân tích cú pháp thực hiện tìm nạp dữ liệu lõi cho bất kỳ mục nhập nào phù hợp với vị từ nơi
uniqueID
bằng với uniqueID được phân tích cú pháp. - Nếu không tìm thấy mục nhập hiện có, trình phân tích cú pháp chèn mục nhập Dữ liệu cốt lõi mới cho thực thể API này, đặt thuộc tính
uniqueID
của nó thành uniqueID được phân tích cú pháp. - Trình phân tích cú pháp lưu bối cảnh đối tượng được quản lý, đẩy dữ liệu mục nhập mới xuống cửa hàng sao lưu SQLite.
Vấn đề ở chi tiết
Giả sử ứng dụng máy chủ và phần mở rộng được phân tích một cách độc lập một phản ứng API cho các tổ chức API cùng một lúc cùng một lúc. Nếu cả ứng dụng máy chủ và tiện ích mở rộng đạt đến Bước 3 trước khi một trong hai kết thúc đã hoàn thành Bước 4, thì cả hai đều sẽ cố gắng chèn mục nhập Dữ liệu cốt lõi mới cho cùng một uniqueID. Khi họ đến Bước 4 và gọi save:
trên bối cảnh đối tượng được quản lý tương ứng của họ, Dữ liệu cốt lõi sẽ vui vẻ tạo các mục trùng lặp.
Theo như tôi biết, Dữ liệu cốt lõi không có bất kỳ cách nào để đánh dấu thuộc tính là duy nhất. Tôi cần một Dữ liệu cốt lõi tương đương với SQLite INSERT OR IGNORE
+ UPDATE
combo.. Hoặc người nào khác tôi cần một cách để "khóa" kho lưu trữ SQLite của kho lưu trữ liên tục, nghe giống như một công thức gây rắc rối.
Có cách tiếp cận nổi tiếng nào cho vấn đề khá mới lạ này được giới thiệu bởi tiện ích mở rộng iOS 8 không?
Tại sao bạn không hủy/tạm dừng yêu cầu GET khi máy chủ chuyển sang chế độ nền? – 3lvis
Tôi đã nhận được các mục nhập trùng lặp này khi dữ liệu cốt lõi bị câm quá, vì điều đó trong bước 2 của Chuỗi dữ liệu lõi nâng cao: nếu có nhiều hơn một kết quả, tôi sẽ xóa các chèn bổ sung. https://github.com/NSElvis/NSManagedObject-ANDYMapChanges/blob/master/Source/NSManagedObject%2BANDYMapChanges.m#L52 – 3lvis