7

iOS8のリリース時にCloudKitを使ったアプリをリリースしたいので、CloudKitをテストしています。以下のコードを使用してデータを保存するのは簡単なようです。

CKRecordID * recordID = [[CKRecordID alloc] initWithRecordName:@"basicRecord"];
CKRecord * record = [[CKRecord alloc] initWithRecordType:@"basicRecordType" recordID:recordID];
[record setValue:@"defaultValue" forKey:@"defaultKey"];
CKDatabase *database = [[CKContainer defaultContainer] publicCloudDatabase];
[database saveRecord:record completionHandler:^(CKRecord *record, NSError *error) {

    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        NSLog(@"Record Saved!");
    }
}];

これでエラーは発生しません。ただし、コードを再度実行しようとすると、レコードの値を次のように変更した可能性があります。

[record setValue:@"newValue" forKey:@"defaultKey"];

変更されたデータを保存するにはどうすればよいですかという質問をするエラーが表示されます。結局のところ、これはクラウドへの保存の基本的な部分です。エラーは以下のとおりです。ご不明な点がございましたら、お気軽にお問い合わせください。

Error: <CKError 0x17024afb0: "Server Record Changed" (14/2017); "Error saving record <CKRecordID: 0x144684a80; basicRecord:(_defaultZone:__defaultOwner__)> to server: (null)"; uuid = 182C497F-966C-418A-9E6A-5563BA6CC6CD; container ID = "iCloud.com.yourcompany.CloudKit">
4

3 に答える 3

13

このエラーはおそらくsaveRecord:、新しいレコードまたはサーバー上のバージョンよりも新しいレコードに対してのみ機能するためです。

このメソッドは、以前に保存されたことがない場合、またはサーバー上のバージョンよりも新しい場合にのみ、レコードを保存します。この方法を使用して、サーバー上の新しいバージョンのレコードを上書きすることはできません。CK データベースのドキュメント

既存のレコード (またはレコードのセット) を変更するための推奨される方法は、競合に対処するためCKModifyRecordsOperationに必要なセットを使用することです。savePolicy

レコードのフィールドを変更した後、このタイプの操作オブジェクトを使用して、それらの変更をデータベースに保存します。(...) レコードを保存するとき、savePolicy プロパティの値によって、サーバーで競合が検出された場合の処理​​方法が決まります。CKModifyRecordsOperation ドキュメント

于 2014-07-01T23:08:14.473 に答える
1

CKRecordのドキュメントから:

新しいレコードは、明示的に iCloud に保存するまで、メモリ内にのみ存在します。

新しい値を設定すると、[record setValue:@"newValue" forKey:@"defaultKey"];すでにレコードが保存されているため、無効になります。

を使用できCKModifyRecordsOperation、ほとんどの状況でそれが望ましいかもしれませんが、そうする必要はありません。fresh を使用してデータをフェッチし、ここで説明されているようCKRecordにそのレコードをフィードするだけです。saveRecord:

于 2015-06-12T11:33:42.720 に答える
0

レコードを保存したら、Cloudkit が追加した RecordID が返されたレコードに含まれるようにフェッチします。

次に、同じフェッチされたレコードで、setValue を使用して、変更するデータを変更します。

次に、CFModifyRecordsOperation を使用できます。以下の例では、cachedCKRecordsServiceCenter に cloudkit からフェッチされたレコードが含まれており、それらのレコードには CloudKit RecordID が含まれています......

           //find this service center in the cached records
            for (_,serviceCenter) in (theModel?.cachedCKRecordsServiceCenter.enumerated())! //is data for logged in Co ONLY with NO Co name attached
            {
                let name = serviceCenter["name"] as! String
                returnValue = "Try Again"
                if name == displayedRecordName
                {
                    serviceCenter.setValue(displayedRecordName! + "_" + (theModel?.companyName)!, forKey: "name") //db values have Co name appended
                    serviceCenter.setValue(label2Text.text, forKey:"street1")
                    serviceCenter.setValue(label3Text.text, forKey:"street2")
                    serviceCenter.setValue(label4Text.text, forKey:"city")
                    serviceCenter.setValue(label5Text.text, forKey:"state")
                    serviceCenter.setValue(label6Text.text, forKey:"zip")
                    serviceCenter.setValue(label7Text.text, forKey:"phone")
                    serviceCenter.setValue(label8Text.text, forKey:"email")
                    serviceCenter.setValue(label9Text.text, forKey:"note")

                    let saveRecordsOperation = CKModifyRecordsOperation()

                    var ckRecordsArray = [CKRecord]()
                    // set values to ckRecordsArray
                    ckRecordsArray.append(serviceCenter)

                    saveRecordsOperation.recordsToSave = ckRecordsArray
                    saveRecordsOperation.savePolicy = .ifServerRecordUnchanged

                    appDelegate.locked = true
                    saveRecordsOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
                        if error != nil {
                            // Really important to handle this here
                            ////////print("ERROR: Unable to update Driver Location: Error= \(error)")
                            self.returnValue = "ERROR: Unable to update Driver Location: ERROR = \(error)"
                            self.appDelegate.locked=false
                        }
                        else
                        {
                             ////print("Successfully updated Service Center")
                            self.appDelegate.locked=false
                            self.returnValue = "Successfully updated Service Center"
                            self.appDelegate.locked=false

                            //reget the data into the cach
                            self.theModel?.fetchServiceCenterFromCloudKit1()
                        }

                    }

                    CKContainer.default().publicCloudDatabase.add(saveRecordsOperation)
                }
            }
于 2017-04-11T17:44:29.677 に答える