2012-04-17 33 views
6

Xem xét mô hình thực thể đơn giản sau đây: Thực thể A có mối quan hệ một với thực thể B được gọi là b. Pháp nhân B có mối quan hệ nghịch đảo-một được gọi là a. Không có mối quan hệ nào là tùy chọn.Tính toàn vẹn và xác thực hợp lệ trong dữ liệu lõi iCloud Đồng bộ hóa

A   B 
b < ----- > a 

Giả sử chúng tôi có hai thiết bị (1) và (2) bắt đầu đồng bộ hóa hoàn toàn. Mỗi đối tượng có một đối tượng của lớp A và một đối tượng của lớp B và chúng được liên kết với nhau. Trên thiết bị 1, chúng ta có các đối tượng A1 và B1, và trên thiết bị B chúng ta có cùng các đối tượng logic A1 và B1.

Bây giờ giả sử rằng những thay đổi simulateous được thực hiện trên mỗi thiết bị:

Trên điện thoại 1, chúng ta xóa B1, B2 chèn, và liên kết với A1 B2. Sau đó, lưu thay đổi.
Trên thiết bị 2, chúng tôi xóa B1, chèn B3 và liên kết A1 với B3. Sau đó lưu thay đổi.

Thiết bị 1 hiện đang cố gắng nhập nhật ký giao dịch từ thiết bị 2. B3 sẽ được chèn và A1 sẽ được liên kết với B3. Cho đến giờ rất tốt, nhưng B2 hiện bị bỏ lại với mối quan hệ a bằng nil. Các mối quan hệ một là không bắt buộc, do đó, lỗi xác thực xảy ra.

Điều tương tự sẽ xảy ra trên thiết bị 2, vì có hai đối tượng B và chỉ một đối tượng A được liên kết với. Do đó, phải luôn có lỗi xác thực vì một trong các đối tượng B phải có mối quan hệ a được đặt thành nil.

Thậm chí tệ hơn, bất kỳ thay đổi nào trong tương lai sẽ luôn để lại một đối tượng B sai lệch xung quanh và do đó sẽ không xác thực được. Trong thực tế, người dùng không thể tự khắc phục sự cố bằng cách đặt lại mối quan hệ. Nó bị hỏng vĩnh viễn.

Câu hỏi đặt ra là, làm cách nào bạn có thể giải quyết lỗi xác thực như thế này? Tất cả điều này xảy ra trước khi thông báo NSPersistentStoreDidImportUbiquitousContentChangesNotification được kích hoạt. Đây không phải là lỗi xác thực trong ứng dụng chính của bạn NSManagedObjectContext, đó là lỗi xác thực xảy ra trong quá trình nhập nhật ký giao dịch ban đầu vào cửa hàng liên tục. Lựa chọn duy nhất tôi có thể nghĩ là có lẽ cố gắng xóa đối tượng B không hợp lệ trong một setter tùy chỉnh (setA:), hoặc trong một phương thức xác thực KVC (validateA:error:) trên chính lớp B, bởi vì chúng dường như được kích hoạt trong quá trình nhập nhật ký giao dịch. Nhưng tôi không chắc chắn rằng các tác dụng phụ như thế này được cho phép, và khi tôi thử nó, có vẻ như kết quả là các thông điệp tường trình khó chịu cho hiệu ứng đó.

Bất cứ ai biết cách xử lý đúng cách này là gì?

Trả lời

2

Kiểm tra chủ đề này trên diễn đàn nhà phát triển của Apple:

https://devforums.apple.com/message/641930#641930

Có một phản hồi từ một nhân viên của Apple. Tóm lại:

1) Đây là lỗi đã biết trong đồng bộ hóa Dữ liệu chính iCloud trong các phiên bản iOS (5.1) và OS X hiện tại (10.7.3).

2) Nếu mối quan hệ là không bắt buộc với vị từ xác thực, đồng bộ hóa sẽ ngừng hoàn toàn. Vì vậy, bạn sẽ cần phải loại bỏ xác thực trong thời gian để giữ cho mọi thứ trôi chảy. Tuy nhiên, làm như vậy sẽ để các thiết bị có dữ liệu không khớp.

3) Không có giải pháp chính thức cho việc này. Một cách tiếp cận, đó là lộn xộn, sẽ là duy trì một thuộc tính riêng biệt theo dõi mối quan hệ. Sau đó, bạn sẽ cần phải quét qua bất kỳ đối tượng nào được thay đổi thông qua iCloud và sửa chữa mối quan hệ nếu nó là không.

Tôi cũng bị lỗi này cắn. Rất bực bội để đối phó với những khách hàng gặp rắc rối. Hy vọng rằng một sửa chữa từ Apple với được ra sớm ...

+0

Cảm ơn, điều đó rất hữu ích. Bài đăng trên diễn đàn dành cho nhà phát triển dường như chỉ ra đây chỉ là vấn đề đối với nhiều mối quan hệ, nhưng tôi không nghĩ đó là trường hợp. Nó sẽ phát sinh trong bất kỳ tình huống mà một mối quan hệ yêu cầu được sửa đổi cùng một lúc. Trong mọi trường hợp, ít nhất tôi biết rằng đây là một lỗi trong khuôn khổ và có thể cố gắng để làm việc xung quanh nó. –

+0

Vấn đề này vẫn còn xảy ra trong 6.x và 10.8.x không? –

+0

Thật không may, có, nó vẫn tồn tại như một vấn đề trong iOS 6.1. – thevoid

1

Trong trường hợp điều này giúp người khác, tôi đã thực hiện một chút tiến bộ hơn làm việc xung quanh lỗi này trong iCloud. Những gì tôi đã làm là vô hiệu hóa xác thực trong quá trình nhập nhật ký giao dịch ban đầu và bật lại nó khi MOC của tôi chuyển sang lưu trữ chính của tôi. Tôi vẫn nhận được lỗi xác thực, tất nhiên, nhưng chúng xảy ra trong phương pháp lưu trữ MOC của tôi, chứ không phải sâu trong khung Dữ liệu cốt lõi, vì vậy tôi có thể sửa lỗi (ví dụ: xóa đối tượng không hợp lệ).

Làm cách nào để 'vô hiệu hóa' xác thực? Cách tôi đang làm nó là ghi đè phương thức xác thực KVC trong lớp con NSManagedObject của tôi, mà tôi đã sử dụng làm lớp gốc cho tất cả các lớp thực thể Dữ liệu cốt lõi.

-(BOOL)validateValue:(__autoreleasing id *)value forKey:(NSString *)key error:(NSError *__autoreleasing *)error 
{ 
    if (![self.managedObjectContext isKindOfClass:[MCManagedObjectContext class]]) { 
     return YES; 
    } 
    else { 
     return [super validateValue:value forKey:key error:error]; 
    } 
} 

Trong ghi đè, tôi kiểm tra lớp của bối cảnh đối tượng được quản lý, và nếu nó là lớp tùy chỉnh của tôi, tôi làm việc xác nhận thông thường bằng cách kết nối với phương pháp siêu. Nếu nó không phải là lớp con tùy chỉnh của tôi, tôi trả lại CÓ để chỉ ra tính hợp lệ. Tất nhiên, bạn có thể làm cho điều này sắc thái hơn, nhưng bạn hy vọng có được ý tưởng: bạn cố gắng xác định xem đây là một trong những tiêu chuẩn của ứng dụng của bạn tiết kiệm hoặc nhập iCloud tiết kiệm, và chi nhánh cho phù hợp.

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