2014-11-19 15 views
18

Để 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 đề

  1. 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.

  2. 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.

  3. 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ự:

  1. Mã API phân tích phân tích các UNIQUEID cho một API cho thực thể.
  2. 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.
  3. 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.
  4. 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?

+0

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

+0

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

Trả lời

10

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?

Có, đó là cách tiếp cận tương tự áp dụng khi sử dụng iCloud với dữ liệu lõi: để cho các bản sao xảy ra, nhưng sau đó đi và làm sạch chúng. Cả hai tình huống đều có nguy cơ tạo các mục trùng lặp và không có cách nào đáng tin cậy để ngăn chặn chúng. Vì bạn có một khóa uniqueID, bạn đang ở trong tình trạng tốt như xa như điều này là có liên quan.

Nó sẽ dễ dàng hơn nhiều, như Dave DeLong lưu ý, để tránh vấn đề ngay từ đầu. Nếu điều đó là không thể, bạn có thể giải quyết nó, với một số công việc phụ.

bản sao Tìm sẽ là một cái gì đó như:

NSError *error = nil; 
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
[moc setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 

NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:@"MyEntityName"]; 
[fr setIncludesPendingChanges:NO]; 

NSExpression *countExpr = [NSExpression expressionWithFormat:@"count:(uniqueID)"]; 
NSExpressionDescription *countExprDesc = [[NSExpressionDescription alloc] init]; 
[countExprDesc setName:@"count"]; 
[countExprDesc setExpression:countExpr]; 
[countExprDesc setExpressionResultType:NSInteger64AttributeType]; 

NSAttributeDescription *uniqueIDAttr = [[[[[_psc managedObjectModel] entitiesByName] objectForKey:@"MyEntityName"] propertiesByName] objectForKey:@"uniqueID"]; 
[fr setPropertiesToFetch:[NSArray arrayWithObjects:uniqueIDAttr, countExprDesc, nil]]; 
[fr setPropertiesToGroupBy:[NSArray arrayWithObject:uniqueIDAttr]]; 

[fr setResultType:NSDictionaryResultType]; 

NSArray *countDictionaries = [moc executeFetchRequest:fr error:&error]; 

này là khá nhiều tương đương với Core Data của một cái gì đó như thế này trong SQL:

SELECT uniqueID, COUNT(uniqueID) FROM MyEntityName GROUP BY uniqueID; 

Bạn nhận được một loạt các từ điển, mỗi trong số đó chứa số uniqueID và số lần giá trị được sử dụng. Chạy qua từ điển và xử lý các bản sao một cách thích hợp.

Tôi đã mô tả chi tiết hơn trong a blog post. Ngoài ra còn có một dự án mẫu từ Apple thể hiện quá trình, được gọi là SharedCoreData, nhưng tôi tin rằng nó chỉ có sẵn như là một phần của WWDC 2012 sample code bundle. Nó cũng được mô tả trong phiên 227 tại hội thảo đó.

9

Dường như cách tiếp cận đơn giản nhất này sẽ đơn giản là tránh nhiều nhà văn ở nơi đầu tiên. Tại sao không chỉ chạy hoàn toàn các tiện ích mở rộng của bạn khỏi dữ liệu được lưu trong bộ nhớ cache và sau đó chỉ cập nhật kho dữ liệu từ ứng dụng iOS chính của bạn?

+0

Đây là phương pháp được đề xuất. – Dhawal

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