CoreData와 REST 웹 서비스를 비동기 적으로 동기화하는 방법과 동시에 모든 REST 오류를 UI에 적절하게 전파하는 방법


85

안녕하세요, 저는 여기서 우리 앱의 모델 레이어를 작업하고 있습니다.

일부 요구 사항은 다음과 같습니다.

  1. iPhone OS 3.0 이상에서 작동합니다.
  2. 데이터 소스는 RESTful Rails 애플리케이션입니다.
  3. Core Data를 사용하여 데이터를 로컬로 캐시해야합니다.
  4. 클라이언트 코드 (우리의 UI 컨트롤러)는 가능한 한 네트워크에 대한 지식이 거의 없어야하며 Core Data API로 모델을 쿼리 / 업데이트해야합니다.

서버 기반 사용자 경험 구축에 대한 WWDC10 세션 117 을 확인하고 Objective Resource , Core ResourceRestfulCoreData 프레임 워크를 확인하는 데 시간을 보냈습니다 .

Objective Resource 프레임 워크는 자체적으로 Core Data와 통신하지 않으며 REST 클라이언트 구현 일뿐입니다. Core Resource 및 RestfulCoreData는 모두 코드에서 Core Data와 통신한다고 가정하고 모델 계층의 백그라운드에서 모든 너트와 볼트를 해결합니다.

지금까지는 모두 괜찮아 보였고 처음에는 Core Resource 또는 RestfulCoreData가 위의 모든 요구 사항을 다룰 것이지만 ... 둘 중 어느 것도 제대로 해결되지 않는 것 같은 몇 가지가 있습니다.

  1. 서버에 로컬 업데이트를 저장하는 동안 메인 스레드를 차단해서는 안됩니다.
  2. 저장 작업이 실패하면 오류가 UI에 전파되고 변경 사항이 로컬 Core Data 저장소에 저장되지 않아야합니다.

Core Resource는 - (BOOL)save:(NSError **)errorManaged Object Context 를 호출 할 때 서버에 모든 요청을 발행 하므로 어떻게 든 서버에 대한 기본 요청의 올바른 NSError 인스턴스를 제공 할 수 있습니다. 그러나 저장 작업이 완료 될 때까지 호출 스레드를 차단합니다. 불합격.

RestfulCoreData는 -save:호출을 그대로 유지하고 클라이언트 스레드에 대한 추가 대기 시간을 도입하지 않습니다. 단지를 감시 NSManagedObjectContextDidSaveNotification한 다음 알림 처리기에서 서버에 해당 요청을 보냅니다. 그러나이 방법으로 -save:호출이 항상 성공적으로 완료 실제로이 실패 할 수 저장이 때문에 일부 서버에 전파 알 수있는 방법이 없다라는 것을 및 클라이언트 코드 (물론, 주어진 코어 데이터가 저장된 변경 괜찮습니다) 404421또는 무엇이든을 서버 측 오류가 발생했습니다. 더욱이 로컬 스토리지는 데이터를 업데이트하지만 서버는 변경 사항에 대해 알지 못합니다. 불합격.

따라서 이러한 모든 문제를 처리 할 수있는 가능한 솔루션 / 일반적인 관행을 찾고 있습니다.

  1. -save:네트워크 요청이 발생하는 동안 호출 스레드가 각 호출 을 차단하는 것을 원하지 않습니다 .
  2. 어떻게 든 UI에서 일부 동기화 작업이 잘못되었다는 알림을 받고 싶습니다.
  3. 서버 요청이 실패하면 실제 Core Data 저장도 실패하고 싶습니다.

어떤 아이디어?


1
와,이 질문을함으로써 얼마나 많은 문제를 구해 주 셨는지 모르겠네요. 나는 현재 호출을 할 때마다 사용자가 데이터를 기다리도록 내 앱을 구현했습니다 (.NET 웹 서비스 임에도 불구하고). 나는 그것을 비동기로 만드는 방법에 대해 생각하고 있었지만 방법을 알 수 없었다. 제공 한 모든 리소스에 감사드립니다!
Tejaswi Yerukalapudi

훌륭한 질문입니다. 감사합니다.
Justin

핵심 리소스에 대한 링크가 끊어졌습니다. 지금 호스팅되는 위치를 아는 사람이 있습니까?

Core Resource는 여전히 GitHub에서 호스팅됩니다 : github.com/mikelaurence/CoreResource
eploko

그리고 원래 사이트는 gitHub에서도 찾을 수 있습니다 : github.com/mikelaurence/coreresource.org
eploko

답변:


26

이 사용 사례에 대해서는 RestKit ( http://restkit.org )을 살펴 봐야 합니다. 원격 JSON 리소스를 모델링하고 로컬 Core Data 지원 캐시에 동기화하는 문제를 해결하도록 설계되었습니다. 사용 가능한 네트워크가 없을 때 캐시에서 완전히 작업하기위한 오프라인 모드를 지원합니다. 모든 동기화는 백그라운드 스레드 (네트워크 액세스, 페이로드 구문 분석 및 관리되는 개체 컨텍스트 병합)에서 발생하며, 진행 상황을 알 수 있도록 풍부한 위임 메서드 집합이 있습니다.


18

세 가지 기본 구성 요소가 있습니다.

  1. UI 작업 및 CoreData에 대한 변경 유지
  2. 그 변화를 서버까지 유지
  3. 서버의 응답으로 UI 새로 고침

NSOperation + NSOperationQueue는 네트워크 요청을 순서대로 유지하는 데 도움이됩니다. 위임 프로토콜은 UI 클래스가 다음과 같이 네트워크 요청의 상태를 이해하는 데 도움이됩니다.

@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

프로토콜 형식은 물론 특정 사용 사례에 따라 다르지만 기본적으로 만드는 것은 변경 사항을 서버에 "푸시"할 수있는 메커니즘입니다.

다음으로 고려해야 할 UI 루프가 있습니다. 코드를 깔끔하게 유지하려면 save를 호출하는 것이 좋을 것입니다. 변경 사항이 자동으로 서버에 푸시됩니다. 이를 위해 NSManagedObjectContextDidSave 알림을 사용할 수 있습니다.

- (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
}

네트워크 작업을 삽입하기위한 계산 오버 헤드는 다소 낮아야하지만 UI에서 눈에 띄는 지연이 발생하는 경우 저장 알림에서 엔티티 ID를 가져 와서 백그라운드 스레드에서 작업을 생성 할 수 있습니다.

REST API가 일괄 처리를 지원하는 경우 전체 배열을 한 번에 전송 한 다음 여러 항목이 동기화되었음을 UI에 알릴 수도 있습니다.

내가 예상하고 "실제"해결책이없는 유일한 문제는 사용자가 변경 사항이 서버에 푸시되어 더 많은 변경을 수행 할 수 있도록 기다리는 것을 원하지 않는다는 것입니다. 내가 만난 유일한 좋은 패러다임은 사용자가 객체를 계속 편집하고 적절할 때 편집을 일괄 처리하도록 허용한다는 것입니다. 즉, 모든 저장 알림을 푸시하지 않습니다.


2

이것은 동기화 문제가되고 해결하기 쉬운 문제가 아닙니다. 내가 할 일은 다음과 같습니다. iPhone UI에서 하나의 컨텍스트를 사용하고 다른 컨텍스트 (및 다른 스레드)를 사용하여 웹 서비스에서 데이터를 다운로드합니다. 모든 것이 완료되면 아래 권장되는 동기화 / 가져 오기 프로세스를 거친 다음 모든 항목을 제대로 가져온 후 UI를 새로 고칩니다. 네트워크에 액세스하는 동안 문제가 발생하면 비 UI 컨텍스트에서 변경 사항을 롤백하십시오. 많은 작업이지만 접근하는 가장 좋은 방법이라고 생각합니다.

핵심 데이터 : 효율적인 데이터 가져 오기

핵심 데이터 : 변경 관리

핵심 데이터 : 핵심 데이터를 사용한 멀티 스레딩


0

다른 스레드 (실제 서버 상호 작용이 발생하는 스레드)에서 실행될 콜백 함수가 필요하고 결과 코드 / 오류 정보에 UI 스레드가 주기적으로 검사 할 반 글로벌 데이터를 넣습니다. 플래그 역할을하는 숫자의 wirting이 원 자성인지 또는 경쟁 조건이 있는지 확인하십시오. 오류 응답이 32 바이트이면 int (원자 적 액세스가 있어야 함)가 필요하고 int를 유지합니다. 더 큰 데이터 블록이 작성 될 때까지 꺼짐 / 거짓 / 준비 안 됨 상태에서 "참"을 작성하여 스위치를 뒤집습니다.

클라이언트 측에서 상관 관계를 저장하려면 해당 데이터를 유지하고 서버에서 확인을받을 때까지 저장하지 않아야합니다. 롤백 옵션의 kinnf가 있는지 확인합니다. 삭제하는 방법은 서버가 실패한 것입니다.

완전한 2 단계 커밋 절차를 수행하지 않는 한 100 % 안전하지 않을 수 있습니다 (클라이언트 저장 또는 삭제는 서버 서버의 신호 후 실패 할 수 있음).하지만 최소한 2 번의 서버 이동 비용이 발생합니다 ( 유일한 롤백 옵션이 삭제 인 경우 비용이 발생할 수 있습니다.)

이상적으로는 작업의 전체 차단 버전을 별도의 스레드에서 수행하는 것이 좋지만 4.0이 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.