나는 iPhone 응용 프로그램에 저장된 핵심 데이터를 iPad 또는 Mac과 같은 여러 장치간에 동기화하는 방법을 연구하고 있습니다. iOS의 Core Data와 함께 사용할 동기화 프레임 워크가 많지 않습니다 (있는 경우). 그러나 나는 다음 개념에 대해 생각하고있다.
- 로컬 코어 데이터 저장소가 변경되고 변경 사항이 저장됩니다. (a) 장치가 온라인 상태 인 경우 변경 세트를 보낸 장치의 장치 ID를 포함하여 변경 세트를 서버로 보내려고합니다. (b) 변경 세트가 서버에 도달하지 않거나 장치가 온라인이 아닌 경우 앱은 변경 세트를 대기열에 추가하여 온라인 상태가 될 때 전송합니다.
- 클라우드에있는 서버는 수신 한 특정 변경 세트를 마스터 데이터베이스와 병합합니다.
- 클라우드 서버에서 변경 세트 (또는 변경 세트 큐)를 병합 한 후 서버는 이러한 변경 세트를 모두 일종의 폴링 시스템을 사용하여 서버에 등록 된 다른 장치로 푸시합니다. (나는 Apple의 Push 서비스를 사용하려고 생각했지만 분명히 의견에 따르면 이것은 실행 가능한 시스템이 아닙니다.)
내가 생각해야 할 멋진 것이 있습니까? ObjectiveResource , Core Resource 및 RestfulCoreData 와 같은 REST 프레임 워크를 살펴 보았습니다 . 물론, 이것들은 모두 Ruby on Rails와 함께 작동하지만, 나는 묶이지 않았지만 시작해야 할 곳입니다. 내 솔루션에 필요한 주요 요구 사항은 다음과 같습니다.
- 메인 스레드를 일시 중지하지 않고 변경 사항을 백그라운드로 보내야합니다.
- 가능한 적은 대역폭을 사용해야합니다.
나는 많은 도전에 대해 생각했다 :
- 다른 장치의 다른 데이터 저장소에 대한 오브젝트 ID가 서버에 연결되어 있는지 확인하십시오. 즉, 데이터베이스에 저장된 개체에 대한 참조를 통해 연결된 개체 ID 및 장치 ID 테이블을 갖게됩니다. 레코드 (DatabaseId [이 테이블에 고유], ObjectId [전체 데이터베이스의 항목에 고유], Datafield1, Datafield2)를 가지며 ObjectId 필드는 다른 테이블 인 AllObjects : (ObjectId, DeviceId, DeviceObjectId)를 참조합니다. 그런 다음 장치가 변경 세트를 푸시하면 로컬 데이터 저장소의 핵심 데이터 개체에서 장치 ID와 objectId를 전달합니다. 그런 다음 내 클라우드 서버는 AllObjects 테이블에서 objectId 및 장치 ID를 확인하고 초기 테이블에서 변경할 레코드를 찾습니다.
- 모든 변경 사항은 타임 스탬프되어야 병합 할 수 있습니다.
- 장치는 너무 많은 배터리를 사용하지 않고 서버를 폴링해야합니다.
- 로컬 장치는 또한 서버에서 변경 사항을 수신 할 때 메모리에 보관 된 내용을 업데이트해야합니다.
여기서 누락 된 것이 있습니까? 이를 가능하게하기 위해 어떤 종류의 프레임 워크를 살펴 봐야합니까?
답변
Dan Grover가 iPhone 2009 컨퍼런스에서 논의한 동기화 전략을주의 깊게 읽고 구현하는 것이 좋습니다 . 여기 에서 pdf 문서로 제공됩니다.
이것은 실행 가능한 솔루션이며 Chris가 설명 한 솔루션과 겹치기 때문에 구현하기가 어렵지 않습니다 (Dan은 여러 응용 프로그램에서 이것을 구현했습니다). 동기화에 대한 심층적이고 이론적 인 토론은 MIT (Russ Cox)와 프린스턴 (Princeton)의 William Josephson의 논문을 참조하십시오.
이는 명백히 수정 된 핵심 데이터에도 동일하게 적용됩니다. 이는 전반적으로 훨씬 강력하고 안정적인 동기화 전략을 제공하지만 올바르게 구현하려면 더 많은 노력이 필요합니다.
편집하다:
Grover의 pdf 파일을 더 이상 사용할 수없는 것 같습니다 (깨진 링크, 2015 년 3 월). 업데이트 : 링크는 웨이 백 머신을 통해 볼 수 있습니다 여기에
iCloud가 마침내 올바른 핵심 데이터 동기화를 지원하는 것으로 보이므로 ZSync 라는 Objective-C 프레임 워크 및 Marcus Zarra가 개발했습니다.
답변
나는 당신이하려는 것과 비슷한 일을했습니다. 내가 배운 것과 내가 어떻게했는지 알려 드리겠습니다.
코어 데이터 객체와 서버의 모델 (또는 db 스키마) 사이에 일대일 관계가 있다고 가정합니다. 서버 내용을 클라이언트와 동기화 된 상태로 유지하려고하지만 클라이언트가 데이터를 수정하고 추가 할 수도 있습니다. 내가 그 권리를 얻는다면 계속 읽으십시오.
동기화를 돕기 위해 4 개의 필드를 추가했습니다.
- sync_status- 이 필드를 코어 데이터 모델에만 추가하십시오. 앱에서 항목에 보류중인 변경 사항이 있는지 확인하는 데 사용됩니다. 다음 코드를 사용합니다. 0은 변경이 없음을 의미하고 1은 서버와 동기화되도록 대기 중임을 의미하고 2는 임시 개체이므로 제거 할 수 있음을 의미합니다.
- is_deleted- 서버 및 코어 데이터 모델에 추가하십시오. Delete 이벤트는 데이터베이스 또는 클라이언트 모델에서 실제로 행을 삭제해서는 안됩니다. 다시 동기화 할 항목이 없기 때문입니다. 이 간단한 부울 플래그를 사용하여 is_deleted를 1로 설정하고 동기화하면 모든 사람이 행복해질 것입니다. 또한 “is_deleted = 0″으로 삭제되지 않은 항목을 쿼리하도록 서버와 클라이언트의 코드를 수정해야합니다.
- last_modified- 서버 및 코어 데이터 모델에 추가하십시오. 이 필드는 레코드에서 변경 될 때마다 서버에 의해 현재 날짜 및 시간으로 자동 업데이트됩니다. 클라이언트가 절대 수정해서는 안됩니다.
- guid- 서버 및 코어 데이터 모델에 글로벌 고유 ID ( http://en.wikipedia.org/wiki/Globally_unique_identifier 참조 ) 필드를 추가하십시오 . 이 필드는 기본 키가되며 클라이언트에서 새 레코드를 작성할 때 중요합니다. 일반적으로 기본 키는 서버에서 증가하는 정수이지만 컨텐츠를 오프라인에서 작성하고 나중에 동기화 할 수 있음을 명심해야합니다. GUID를 사용하면 오프라인 상태에서 키를 만들 수 있습니다.
클라이언트에서 변경 사항이 있거나 서버와 동기화해야 할 때마다 모델 오브젝트에서 sync_status를 1로 설정하는 코드를 추가하십시오. 새 모델 객체는 GUID를 생성해야합니다.
동기화는 단일 요청입니다. 요청에는 다음이 포함됩니다.
- 모델 객체의 MAX last_modified 타임 스탬프 이렇게하면이 타임 스탬프 이후에만 변경을 원한다는 것을 서버에 알립니다.
- sync_status = 1 인 모든 항목을 포함하는 JSON 배열입니다.
서버는 요청을 받고 다음을 수행합니다.
- JSON 배열에서 내용을 가져 와서 포함하는 레코드를 수정하거나 추가합니다. last_modified 필드가 자동으로 업데이트됩니다.
- 서버는 요청에서 전송 된 타임 스탬프보다 last_modified 타임 스탬프가 큰 모든 객체가 포함 된 JSON 배열을 반환합니다. 여기에는 방금받은 개체가 포함되며 레코드가 서버에 성공적으로 동기화되었다는 확인의 역할을합니다.
앱이 응답을 수신하고 다음을 수행합니다.
- JSON 배열에서 내용을 가져 와서 포함하는 레코드를 수정하거나 추가합니다. 각 레코드는 sync_status를 0으로 설정합니다.
도움이 되길 바랍니다. 레코드와 모델이라는 단어를 서로 바꿔서 사용했지만 아이디어가 있다고 생각합니다. 행운을 빕니다.
답변
여전히 갈 길을 찾고 있다면 Couchbase 모바일을 살펴보십시오. 이것은 기본적으로 당신이 원하는 모든 것을합니다. ( http://www.couchbase.com/nosql-databases/couchbase-mobile )
답변
@Cris와 비슷하게 클라이언트와 서버 간의 동기화를 위해 클래스를 구현했으며 지금까지 알려진 모든 문제를 해결했습니다 (서버와 데이터를주고 받거나 타임 스탬프를 기반으로 충돌을 병합하고 신뢰할 수없는 네트워크 조건에서 중복 항목을 제거하고 중첩 된 데이터를 동기화하고 파일 등 ..)
클래스에 어떤 엔티티와 어떤 컬럼을 동기화해야하며 서버가 어디에 있는지 알려 주기만하면됩니다.
M3Synchronization * syncEntity = [[M3Synchronization alloc] initForClass: @"Car"
andContext: context
andServerUrl: kWebsiteUrl
andServerReceiverScriptName: kServerReceiverScript
andServerFetcherScriptName: kServerFetcherScript
ansSyncedTableFields:@[@"licenceNumber", @"manufacturer", @"model"]
andUniqueTableFields:@[@"licenceNumber"]];
syncEntity.delegate = self; // delegate should implement onComplete and onError methods
syncEntity.additionalPostParamsDictionary = ... // add some POST params to authenticate current user
[syncEntity sync];
github.com/knagode/M3Synchronization 에서 소스, 실제 예제 및 추가 지침을 찾을 수 있습니다 .
답변
푸시 알림을 통해 데이터를 업데이트하도록 사용자에게 알립니다. 앱에서 백그라운드 스레드를 사용하여 클라우드 서버에서 로컬 데이터 및 데이터를 확인하고 서버에서 변경이 발생하는 동안 로컬 데이터를 변경하거나 그 반대로 변경하십시오.
따라서 가장 어려운 부분은 어느 쪽이 무효화되는지를 추정하는 것입니다.
이것이 당신을 도울 수 있기를 바랍니다.
답변
방금 SynCloud라고하는 새로운 Core Data Cloud Syncing API의 첫 번째 버전을 게시했습니다. SynCloud는 다중 사용자 동기화 인터페이스를 허용하므로 iCloud와 많은 차이점이 있습니다. 다중 테이블 관계형 데이터를 허용하기 때문에 다른 동기화 API와 다릅니다.
http://www.syncloudapi.com 에서 자세한 내용을 확인하십시오.
iOS 6 SDK로 빌드하면 2012 년 9 월 27 일 현재 최신 상태입니다.
답변
GUID 문제에 대한 좋은 해결책은 “분산 ID 시스템”이라고 생각합니다. 올바른 용어가 무엇인지 잘 모르겠지만 MS SQL 서버 문서가 그것을 호출하는 데 사용한 것입니다 (SQL은 분산 / 동기화 데이터베이스 에이 방법을 사용 / 사용했습니다). 꽤 간단합니다.
서버는 모든 ID를 할당합니다. 동기화가 완료 될 때마다 가장 먼저 확인되는 것은 “이 클라이언트에 몇 개의 ID가 남아 있습니까?”입니다. 클라이언트가 부족한 경우 서버에 새 ID 블록을 요청합니다. 그런 다음 클라이언트는 새 레코드에 해당 범위의 ID를 사용합니다. 다음 동기화 이전에 “절대로”실행되지 않을 정도로 큰 블록을 할당 할 수 있지만 시간이지나면서 서버가 부족할 정도로 큰 블록을 할당 할 수없는 경우 대부분의 요구에 적합합니다. 클라이언트가 부족한 경우 처리가 매우 간단 할 수 있습니다. 사용자에게 “동기화 할 때까지 더 이상 항목을 추가 할 수 없습니다”라고 말하십시오. 많은 항목을 추가하는 경우 오래된 데이터를 피하기 위해 동기화하지 않아야 어쨌든 문제?
임의 GUID는 100 % 안전하지 않으며 일반적으로 표준 ID (128 비트 대 32 비트)보다 훨씬 길어야하기 때문에 이것이 임의 GUID를 사용하는 것보다 우수하다고 생각합니다. 일반적으로 ID별로 색인이 있으며 종종 ID 번호를 메모리에 유지하므로 작게 유지하는 것이 중요합니다.
실제로 답변으로 게시하고 싶지는 않았지만 누구나 의견으로 볼 수 있다는 것을 모르겠습니다.이 주제에 중요하며 다른 답변에는 포함되지 않는다고 생각합니다.