Cách đồng bộ hóa CoreData và dịch vụ web REST một cách không đồng bộ và đồng thời truyền tải đúng cách mọi lỗi REST vào giao diện người dùng


85

Này, tôi đang làm việc trên lớp mô hình cho ứng dụng của chúng tôi ở đây.

Một số yêu cầu như sau:

  1. Nó sẽ hoạt động trên iPhone OS 3.0+.
  2. Nguồn dữ liệu của chúng tôi là một ứng dụng RESTful Rails.
  3. Chúng ta nên lưu dữ liệu cục bộ bằng cách sử dụng Core Data.
  4. Mã máy khách (bộ điều khiển giao diện người dùng của chúng tôi) phải có ít kiến ​​thức về bất kỳ nội dung mạng nào nhất có thể và nên truy vấn / cập nhật mô hình bằng API dữ liệu cốt lõi.

Tôi đã xem WWDC10 Session 117 về Xây dựng trải nghiệm người dùng hướng máy chủ, đã dành một chút thời gian để kiểm tra Tài nguyên mục tiêu , Tài nguyên cốt lõiDữ liệu RestfulCoreData .

Khung tài nguyên mục tiêu không tự nói chuyện với Dữ liệu cốt lõi và chỉ đơn thuần là triển khai máy khách REST. Core Resource và RestfulCoreData đều giả định rằng bạn nói chuyện với Core Data trong mã của bạn và chúng giải quyết tất cả các lỗi và bu lông trong nền trên lớp mô hình.

Tất cả đều có vẻ ổn cho đến nay và ban đầu tôi mặc dù Core Resource hoặc RestfulCoreData sẽ bao gồm tất cả các yêu cầu trên, nhưng ... Có một vài điều dường như không có gì xảy ra để giải quyết chính xác:

  1. Chuỗi chính sẽ không bị chặn trong khi lưu các bản cập nhật cục bộ vào máy chủ.
  2. Nếu thao tác lưu không thành công, lỗi sẽ được truyền tới giao diện người dùng và không có thay đổi nào được lưu vào bộ lưu trữ Dữ liệu lõi cục bộ.

Core Resource xảy ra để đưa ra tất cả các yêu cầu của nó tới máy chủ khi bạn gọi - (BOOL)save:(NSError **)errortrên Ngữ cảnh đối tượng được quản lý của mình và do đó có thể cung cấp phiên bản NSError chính xác của các yêu cầu cơ bản đến máy chủ bị lỗi bằng cách nào đó. Nhưng nó chặn luồng gọi cho đến khi hoạt động lưu kết thúc. THẤT ​​BẠI.

RestfulCoreData giữ -save:nguyên các cuộc gọi của bạn và không giới thiệu thêm bất kỳ thời gian chờ đợi nào cho chuỗi ứng dụng khách. Nó chỉ đơn thuần theo dõi NSManagedObjectContextDidSaveNotificationvà sau đó đưa ra các yêu cầu tương ứng đến máy chủ trong trình xử lý thông báo. Nhưng cách này -save:gọi luôn hoàn thành công (tốt, đưa dữ liệu cốt lõi là ổn với những thay đổi lưu) và mã khách hàng mà thực sự gọi là nó không có cách nào để biết sự tiết kiệm có thể đã thất bại trong việc tuyên truyền đến máy chủ vì một số 404hoặc 421hoặc bất cứ điều gì đã xảy ra lỗi phía máy chủ. Và thậm chí nhiều hơn nữa, bộ lưu trữ cục bộ sẽ được cập nhật dữ liệu, nhưng máy chủ không bao giờ biết về những thay đổi. THẤT ​​BẠI.

Vì vậy, tôi đang tìm kiếm một giải pháp khả thi / các phương pháp phổ biến để giải quyết tất cả những vấn đề sau:

  1. Tôi không muốn chuỗi cuộc gọi bị chặn trên mỗi -save:cuộc gọi trong khi các yêu cầu mạng xảy ra.
  2. Tôi muốn bằng cách nào đó nhận được thông báo trong giao diện người dùng rằng một số hoạt động đồng bộ hóa đã bị lỗi.
  3. Tôi muốn lưu Dữ liệu lõi thực tế cũng không thành công nếu các yêu cầu máy chủ không thành công.

Có ý kiến ​​gì không?


1
Chà, bạn không biết bạn đã cứu tôi bao nhiêu rắc rối khi đặt câu hỏi này. Tôi hiện đã triển khai ứng dụng của mình để khiến người dùng đợi dữ liệu mỗi khi tôi thực hiện cuộc gọi (mặc dù với dịch vụ web .NET). Tôi đã suy nghĩ về một cách để làm cho nó không đồng bộ nhưng không thể tìm ra cách làm. Cảm ơn tất cả các tài nguyên bạn đã cung cấp!
Tejaswi Yerukalapudi

Câu hỏi hay, cảm ơn bạn.
Justin

Liên kết đến Core Resource bị hỏng, có ai biết nó được lưu trữ ở đâu không?

Core Resource vẫn được lưu trữ trên GitHub tại đây: github.com/mikelaurence/CoreResource
eploko

Và trang web gốc cũng có thể được tìm thấy trên gitHub: github.com/mikelaurence/coreresource.org
eploko

Câu trả lời:


26

Bạn thực sự nên xem RestKit ( http://restkit.org ) cho trường hợp sử dụng này. Nó được thiết kế để giải quyết các vấn đề về mô hình hóa và đồng bộ hóa các tài nguyên JSON từ xa với bộ nhớ đệm được sao lưu Dữ liệu lõi cục bộ. Nó hỗ trợ một chế độ ngoại tuyến để làm việc hoàn toàn từ bộ nhớ cache khi không có mạng. Tất cả quá trình đồng bộ hóa diễn ra trên một chuỗi nền (truy cập mạng, phân tích cú pháp tải trọng và hợp nhất ngữ cảnh đối tượng được quản lý) và có một tập hợp phong phú các phương thức ủy quyền để bạn có thể biết điều gì đang xảy ra.


18

Có ba thành phần cơ bản:

  1. Hành động giao diện người dùng và tiếp tục thay đổi đối với CoreData
  2. Kiên trì thay đổi đó cho đến máy chủ
  3. Làm mới giao diện người dùng với phản hồi của máy chủ

NSOperation + NSOperationQueue sẽ giúp giữ các yêu cầu mạng có trật tự. Giao thức ủy quyền sẽ giúp các lớp UI của bạn hiểu các yêu cầu mạng đang ở trạng thái nào, chẳng hạn như:

@protocol NetworkOperationDelegate
  - (void)operation:(NSOperation *)op willSendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
  - (void)operation:(NSOperation *)op didSuccessfullySendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
  - (void)operation:(NSOperation *)op encounteredAnError:(NSError *)error afterSendingRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
@end

Định dạng giao thức tất nhiên sẽ phụ thuộc vào trường hợp sử dụng cụ thể của bạn nhưng về cơ bản những gì bạn đang tạo là một cơ chế mà các thay đổi có thể được "đẩy" lên máy chủ của bạn.

Tiếp theo là vòng lặp giao diện người dùng cần xem xét, để giữ cho mã của bạn sạch sẽ, tốt hơn là bạn nên gọi lưu: và để các thay đổi tự động được đẩy lên máy chủ. Bạn có thể sử dụng thông báo NSManagedObjectContextDidSave cho việc này.

- (void)managedObjectContextDidSave:(NSNotification *)saveNotification {
  NSArray *inserted = [[saveNotification userInfo] valueForKey:NSInsertedObjects];
  for (NSManagedObject *obj in inserted) {
    //create a new NSOperation for this entity which will invoke the appropraite rest api
    //add to operation queue
  }

  //do the same thing for deleted and updated objects
}

Chi phí tính toán để chèn các hoạt động mạng phải khá thấp, tuy nhiên nếu nó tạo ra độ trễ đáng chú ý trên giao diện người dùng, bạn có thể chỉ cần lấy id thực thể ra khỏi thông báo lưu và tạo các hoạt động trên một chuỗi nền.

Nếu API REST của bạn hỗ trợ theo lô, bạn thậm chí có thể gửi toàn bộ mảng cùng một lúc và sau đó thông báo cho bạn giao diện người dùng rằng nhiều thực thể đã được đồng bộ hóa.

Vấn đề duy nhất tôi thấy trước, và không có giải pháp "thực sự" là người dùng sẽ không muốn đợi các thay đổi của họ được đẩy lên máy chủ để được phép thực hiện thêm các thay đổi. Mô hình tốt duy nhất mà tôi đã gặp là bạn cho phép người dùng tiếp tục chỉnh sửa các đối tượng và hàng loạt các chỉnh sửa của họ với nhau khi thích hợp, tức là bạn không nhấn vào mọi thông báo lưu.


2

Đây trở thành một vấn đề đồng bộ và không dễ giải quyết. Đây là những gì tôi phải làm: Trong giao diện người dùng iPhone của bạn, sử dụng một ngữ cảnh và sau đó sử dụng một ngữ cảnh khác (và một chuỗi khác) tải xuống dữ liệu từ dịch vụ web của bạn. Sau khi tất cả ở đó, hãy thực hiện các quy trình đồng bộ hóa / nhập được đề xuất bên dưới và sau đó làm mới giao diện người dùng của bạn sau khi mọi thứ đã được nhập đúng cách. Nếu mọi thứ trở nên tồi tệ khi truy cập mạng, chỉ cần khôi phục các thay đổi trong ngữ cảnh không phải UI. Đó là một đống công việc, nhưng tôi nghĩ đó là cách tốt nhất để tiếp cận nó.

Dữ liệu cốt lõi: Nhập dữ liệu hiệu quả

Dữ liệu cốt lõi: Quản lý thay đổi

Dữ liệu cốt lõi: Đa luồng với dữ liệu cốt lõi


0

Bạn cần một hàm gọi lại sẽ chạy trên chuỗi khác (một trong những nơi xảy ra tương tác máy chủ thực tế) và sau đó đặt mã kết quả / thông tin lỗi một dữ liệu bán toàn cầu sẽ được kiểm tra định kỳ bởi chuỗi giao diện người dùng. Hãy đảm bảo rằng sự vắt sổ của số đóng vai trò là lá cờ là nguyên tử hoặc bạn sẽ có một điều kiện chạy đua - giả sử nếu phản hồi lỗi của bạn là 32 byte, bạn cần một int (whihc nên có acc nguyên tử) và sau đó bạn giữ nguyên số nguyên đó ở trạng thái tắt / sai / chưa sẵn sàng cho đến khi khối dữ liệu lớn hơn của bạn được viết và chỉ sau đó viết "true" để lật công tắc để nói.

Đối với việc lưu tương quan ở phía máy khách, bạn phải chỉ giữ dữ liệu đó và không lưu nó cho đến khi bạn nhận được sự đồng ý từ máy chủ và đảm bảo rằng bạn có tùy chọn khôi phục dữ liệu - giả sử cách xóa là máy chủ không thành công.

Hãy lưu ý rằng nó sẽ không bao giờ an toàn 100% trừ khi bạn thực hiện đầy đủ quy trình cam kết 2 giai đoạn (lưu hoặc xóa máy khách có thể không thành công sau khi có tín hiệu từ máy chủ của máy chủ) nhưng điều đó sẽ khiến bạn tốn ít nhất 2 chuyến đi đến máy chủ ( có thể khiến bạn mất 4 nếu tùy chọn khôi phục duy nhất của bạn bị xóa).

Lý tưởng nhất là bạn thực hiện toàn bộ phiên bản chặn của hoạt động trên một chuỗi riêng biệt nhưng bạn cần 4.0 cho điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.