Skip to content

iCloud 사용방법

songwongeun edited this page Jan 25, 2019 · 14 revisions

Reference

여러가지 종류의 iCloud 스토리지

  1. Key-value storage : 환경설정, 세팅, 간단한 앱 상태같은 개별적인 값을 저장하기 위함.
  2. iCloud document storage: 워드프로세싱 문서, 그림 같은 사용자가 볼 수 있는 파일기반의 정보와 그리고 복합적인 앱상태를 저장하기 위함.
  3. CloudKit storage: iCloud에 당신 자신의 구조화된 데이터를 관리하고 당신의 사용자간에 데이터를 공유하기 위함.
  4. Core Data storage: shoebox 스타일 앱과 서버기반, 구조화된 콘텐트를 위한 멀티디바이스 데이터베이스 솔루션을 위한 코어 데이터 스토리지. iCloud Core Data 스토리지는 iCloud document 스토리지에 기반해 설계되고 같은 iCloud APIs를 채용한다. (The use of iCloud with Core Data has been deprecated)

iCloud에 저장해도 되는 것들과 저장하지 말아야 할 것들

  • iCloud에 저장해도 되는 것들:
    • 사용자 문서
    • 사용자가 생성한 데이터를 담고있는 앱에 한정된 파일
    • 환경설정과 앱 상태(key-value 스토리지사용- 사용자의 iCloud 스토리지 할당량에 불리하게 여겨지지 않는것들)
    • SQLite 데이터베이스변경사항로그파일 ( SQLite 데이터베이스의 저장파일은 iCloud에저장하면 안된다)
  • iCloud에 저장하지 말아야 할 것들:
    • 캐시파일
    • 임시파일
    • 앱이 생성하고 재생성 할 수 있는 App support 파일
    • 용량이 큰 다운로드된 데이터파일

CloudKit 활성화하기

  1. CloudKit을 사용하기 전에 Xcode 프로젝트에서 앱의 타겟이 iCloud와 Cloudkit을 사용하도록 활성화 해야한다.(Apple developer program에 가입되어 있어야 iCloud를 사용 할 수 있다.)
  2. Xcode를 사용해서 클라우드킷을 설정하면 Xcode는 entitlements(자격) 파일을 앱에 추가하고 앱의 번들ID를 기반으로한 디폴트 컨테이너를 사용하도록 설정한다.
  3. 추가적인 컨테이너를 생성할 수 있고 그 컨테이너를 다른앱과 공유할 수도 있다.
  4. Xcode가 해당 컨테이너를 생성하자마자 CloudKit Dashboard 웹 툴(웹페이지)로 컨테이너에 접근할 수 있게된다.

Enabling CloudKit in Your App

CloudKit 구성요소

  1. container

    • iCloud container 또는 ubiquity container라고 불리며 CKContainer로 표현된다.
    • 여러개의 앱과 사용자가 iCloud에 접근 할 수 있지만 데이터는 containers라는 파티션에 분리, 캡슐화되어 저장
    • 앱에 속한 container가 다른 개발자의 앱으로 액세스는 불가, 앱은 컨테이너 공유 가능, 여러 앱이 컨테이너를 공유 할 수 있고 하나의 앱이 여러 컨테이너를 사용할 수 있다.
    • 기본적으로 app하나에 default 컨테이너 하나 존재, custom 컨테이너 추가 가능
    • Default 컨테이너의 identifier는 앱의 번들 ID와 일치 지정한 모든 containers의 Id는 모든 개발자 계정에서 고유해야 한다.
    • 런타임동안 CKContainer 객체를 사용해서 특정 컨테이너에 대한 작업을 수행할 수 있다.
  2. database

    • 각 컨테이너는 공개(public) 데이터베이스와 비공개(private) 데이터베이스로 나누어지고 각각은 CKDatabase 객체에 의해서 표현된다.
    • 모든 사용자는 공개 데이터베이스를 읽기 가능하고, 쓰기는 iCloud credential이 필요하다.
    • 앱의 각 사용자마다 비공개 데이터베이스가 있지만 앱은 현재사용자의 비공개 데이터베이스만 엑세스 가능하다. 읽기 쓰기 둘다 iCloud credential 필요하다.
    • 만일 앱이 공개 데이터베이스에서 데이터를 읽는 것 이상의 작업을 수행한다면 레코드를 저장하기전에 사용자가 로그인한 상태인지 확인할 것. 에러를 방지하려면 사용자가 로그인할 때까지 레코드를 저장하는 UI는 비활성화 해 둘 것.
  3. record

    • CKRecord 클래스 인스턴스에 의해서 표현
    • 당신은 operation 객체 또는 CKContainer 와 CKDatabase 클래스의 편의 메써드를 사용해서 레코드를 가져오고(Fetch) 저장한다.
    • Operation 객체는 한번에 여러 레코드에서 작동될 수 있고, 레코드가 적절한 순서로 저장될 수 있도록 종속성을 사용하여 구성될 수 있다. Operation Operation 객체는 NSOperation 클래스를 기반으로 하며 당신앱의 다른 작업흐름과 통합될 수 있다.
    • 원하는 레코드의 ID를 알고 있다면 fetch를 사용, 모른다면 CKQuery와 predicate을 사용하여 레코드를 쿼리할 수 있는 기능을 제공한다.
    • subscriptions(구독)을 사용해서 데이터베이스의 특정 부분이 변경될 때 서버가 알릴 수 있도록 할 것(Subscribing to Record Changes)
  4. field

Field Type Class Description
Asset CKAsset 레코드와 연관되지만 별도로 저장되는 큰 용량의 파일
Bytes NSData 레코드와 함께 저장되는 바이트 버퍼용 레퍼
Date/Time NSData 날짜/시간
Double NSNumber Double
Int(64) NSNumber Integer
Location CLLocation 지리적 좌표와 고도
Reference CKReference 한 객체와 다른 객체와의 관계
String NSString 변경할 수 없는 텍스트 문자열(immutable)
List NSArray 위의 필드 유형 중 하나의 배열

사용예시

import CKCloud
  1. 컨테이너 및 데이터베이스 가져오기
let myContainer = CKContainer.default() // .entitlements file에 있는 default 컨테이너 선택
let publicDatabase = myContainer.publicCloudDatabase
// let privateDatabase = myContainer.privateCloudDatabase
  1. 레코드 생성 및 필드 추가
let entryRecordID = CKRecordID(recordName: "115") // dashboard에서 선 레코드ID
let entryRecord = CKRecord(recordType: "Entry", recordID: EntryRecordID)

entryRecord["title"] = "Hello world" as NSString
entryRecord["date"] = NSDate.init() as NSDate
entryRecord["content"] = "Hi, nice to meet you." as NSString
  1. 레코드 저장하기
publicDatabase.save(entryRecord) {
    (record, error) in
    if let error = error {
        // Insert error handling
        return
    }
    // Insert successfully saved record code
}
  1. 모든 레코드(Entry) 찾기
let predicate = NSPredicate(value: true) // 모든 레코드를 찾는 predicate
let query = CKQuery(recordType: "Entry", predicate: predicate)

privateDatabase.perform(query, inZoneWith: nil) { 
    (results, error) in
    if let error = error {
        // Insert error handling
        return
    }
    // Insert successfully read all records code
}
  1. 모든 레코드(Entry) 삭제하기
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "Entry", predicate: predicate)
privateDB.perform(query, inZoneWith: nil) { 
    (results, error) in
    if let error = error {
        // Insert error handling
        return
    }

    if let entries = results {
        for entry in entries {
            self.privateDB.delete(withRecordID: entry.recordID) { _, error in
            if let error = error {
                // Insert error handling
                return
            }
            // Insert successfully deleted record code
        }
    }
}