为什么要在CloudKit中批量删除记录的CKModifyRecordsOperation不删除记录? [英] Why is CKModifyRecordsOperation to batch delete records in CloudKit not deleting records?

查看:90
本文介绍了为什么要在CloudKit中批量删除记录的CKModifyRecordsOperation不删除记录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有用于从CloudKit的私有数据库中批量删除记录的代码,但是无法正常工作。 (我还注意到,保存的记录不会保留。)我使用的是带有我个人使用的真实Apple ID的实际iPhone 8,而不是开发者帐户。使用iPhone 8模拟器,我得到相同的结果。使用iPhone 8 Simulator以与开发人员帐户相同的Apple ID登录到iCloud时,我没有出现此问题。

I have code to batch delete records from the private database in CloudKit, but it's not working. (I also noticed that the records I saved are not remaining.) I am using an actual iPhone 8 with an actual Apple ID I personally use, not a developer account. I get the same results with an iPhone 8 Simulator. I don't have this problem when I log in to iCloud with the same Apple ID as my developer account using iPhone 8 Simulator.

在此帖子的答案没有给我解决方法之后,我认为关于此问题的最重要的事情是,当我使用非我的Apple ID时会发生此问题开发者帐户。我在不是我的开发人员帐户的两个不同的Apple ID上进行了尝试。

After answers to this post have not given me a solution, I think the most important thing about this problem is that it occurs when I use an Apple ID that is not my developer account. I tried it on two different Apple IDs that are not my developer account. Could it be a setting I'm overlooking somewhere?

stackoverflow上没有类似的帖子可以解决此问题。

None of the similar posts on stackoverflow solves this problem.

看起来应该删除代码的某些记录实际上已删除,但有些则没有。当我再次运行代码时,仍然存在记录,但是记录数比以前少了。

It looks like some of the records that the code is supposed to delete is actually deleted, but some are not. When I run the code again, there exists records still, but about one less the number as before.

这是我的代码:

class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let splitViewController = window!.rootViewController as! UISplitViewController
        let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
        navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
        splitViewController.delegate = self

        deleteRecords()
        return true
    }

}

let privateDatabase = CKContainer.default().privateCloudDatabase

func deleteRecords() {

    print("deleteRecords()")

    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: DatabaseNameStrings.recordTypeAffirmation, predicate: predicate)

    privateDatabase.perform(query, inZoneWith: nil) {

        (records: [CKRecord]?, error: Error?) in

        if error != nil {

            print(error as Any)

        } else {

            if let records = records {

                print("records.count=", records.count)

                let recordIDsToDelete = records.map { $0.recordID }
                print("recordIDsToDelete:")
                print(recordIDsToDelete)
                let operation = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: recordIDsToDelete)
                operation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
                    if error == nil {
                        print("Batch delete records!")
                        print("number of records deleted:", deletedRecordIDs?.count as Any)
                        printNumberOfRecords()
                    } else {
                        print(error as Any)
                    }
                }
                privateDatabase.add(operation)

            }

        }

    }
}

func printNumberOfRecords() {

    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: DatabaseNameStrings.recordTypeAffirmation, predicate: predicate)

    privateDatabase.perform(query, inZoneWith: nil) {

        (records: [CKRecord]?, error: Error?) in

        if error != nil {

            print(error as Any)

        } else {

            if let records = records {

                print("Number of records in CloudKit=", records.count)

            }

        }

    }

}

以下是调试窗口中的输出第一次执行代码:

Here is the output in the debug window from the first run of the code:

deleteRecords()
records.count= 93
recordIDsToDelete:
[<CKRecordID: 0x280bbcb00; recordName=B33A3F23-23D3-44C6-AEBC-86DD718DBB62, zoneID=...>, ... ]
Batch delete records!
number of records deleted: Optional(93)
Number of records in CloudKit= 67

这是第二次代码运行在调试窗口中的输出:

Here is the output in the debug window from the second run of the code:

deleteRecords()
records.count= 92
recordIDsToDelete:
[<CKRecordID: 0x280080d00; recordName=BBA5B236-A036-4AC9-82E1-165D3B003E23, zoneID=...>, ... ]
Batch delete records!
number of records deleted: Optional(92)
Number of records in CloudKit= 52

当我使用此代码而不是deleteRecords()...

When I use this code instead of deleteRecords() ...

func deleteRecordsOneAtATime() {

    print("deleteRecordsOneAtATime()")

    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: DatabaseNameStrings.recordTypeAffirmation, predicate: predicate)

    privateDatabase.perform(query, inZoneWith: nil) {

        (records: [CKRecord]?, error: Error?) in

        if error != nil {

            print(error as Any)

        } else {

            if let records = records {

                print("records.count=", records.count)

                let recordIDsToDelete = records.map { $0.recordID }
                print("recordIDsToDelete:")
                print(recordIDsToDelete)

                for recordID in recordIDsToDelete {

                    privateDatabase.delete(withRecordID: recordID) {
                        (localRecordID: CKRecord.ID?, error: Error?) in
                        if error != nil {
                            print("error:\n", error as Any)
                        } else {
                            if localRecordID != nil {
                                print("localRecordID:", localRecordID as Any)
                            }
                        }
                    }

                printNumberOfRecords()

                }

            }

        }

    }

}

I在调试窗口中获取:

I get in the debug window:

deleteRecordsOneAtATime()
Number of records in CloudKit= 97
records.count= 97
recordIDsToDelete:
[<CKRecordID: 0x283622ec0; recordName=600B7BFE-04FE-4F63-BC4C-5AD1AE08908D, zoneID=...>, ... ]
localRecordID: Optional(<CKRecordID: 0x2821ff320; recordName=8E8CD0F0-FDF5-4CB9-B16C-5CF91C3503A2, zoneID=_defaultZone:__defaultOwner__>)
localRecordID: Optional(<CKRecordID: 0x2821ff320; recordName=8E0A0816-1B05-4707-A4E7-C40762E68663, zoneID=_defaultZone:__defaultOwner__>)
localRecordID: Optional(<CKRecordID: 0x28210b200; recordName=8E127624-F1D3-401E-ADF2-BB97354FCA98, zoneID=_defaultZone:__defaultOwner__>)
...
Number of records in CloudKit= 87
localRecordID: Optional(<CKRecordID: 0x282108660; recordName=962639D1-83E6-40D2-A57D-F70ADCEBED08, zoneID=_defaultZone:__defaultOwner__>)
localRecordID: Optional(<CKRecordID: 0x28210ff20; recordName=968D62AB-523E-464B-94B8-3C90E0382AB6, zoneID=_defaultZone:__defaultOwner__>)
localRecordID: Optional(<CKRecordID: 0x28210faa0; recordName=96C92DD2-ED27-4FED-8320-44D03981B04F, zoneID=_defaultZone:__defaultOwner__>)
localRecordID: Optional(<CKRecordID: 0x2821085a0; recordName=96A2D515-D3E7-475E-B609-8389DE4B88D1, zoneID=_defaultZone:__defaultOwner__>)

这是我的最新代码仍然无法正常工作:

Here is my latest code that still doesn't work:

func removeRecords() {

    print("removeRecords()")

    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: DatabaseNameStrings.recordTypeAffirmation, predicate: predicate)

    privateDatabase.perform(query, inZoneWith: nil) {

        (records: [CKRecord]?, error: Error?) in

        if error != nil {

            print(error as Any)

        } else {

            if let records = records {

                print("records.count=", records.count)

                let recordIDsToDelete = records.map { $0.recordID }
                print("recordIDsToDelete:")
                print(recordIDsToDelete)

                DispatchQueue.main.async {

                    if recordIDsToDelete.count > 50 {
                        let slice = Array(recordIDsToDelete[0 ..< 50])
                        let leftOver = Array(recordIDsToDelete[50 ... recordIDsToDelete.count-1])

                        privateDatabase.remove(recordsWith: slice) {
                            (result: Result<Void, Error>) in
                            print("result:", result)
                            switch result {
                            case .failure(let err):
                                print("failure")
                                print(err)
                            case .success(()):
                                print("success")
                                DispatchQueue.main.async {
                                    privateDatabase.remove(recordsWith: leftOver) {
                                        (result: Result<Void, Error>) in
                                        print("result:", result)
                                        switch result {
                                        case .failure(let err):
                                            print("failure")
                                            print(err)
                                        case .success(()):
                                            print("success")
                                        }
                                        print("type of result:", type(of: result))
                                    }
                                }
                            }
                            print("type of result:", type(of: result))
                        }

                    } else {

                        privateDatabase.remove(recordsWith: recordIDsToDelete) {
                            (result: Result<Void, Error>) in
                            print("result:", result)
                            switch result {
                            case .failure(let err):
                                print("failure")
                                print(err)
                            case .success(()):
                                print("success")
                            }
                            print("type of result:", type(of: result))
                        }

                    }





                    privateDatabase.remove(recordsWith: recordIDsToDelete) {
                        (result: Result<Void, Error>) in
                        print("result:", result)
                        switch result {
                        case .failure(let err):
                            print("failure")
                            print(err)
                        case .success(()):
                            print("success")
                        }
                        print("type of result:", type(of: result))
                    }

                }

            }

        }

    }

}

extension CKDatabase {
    func remove(
        recordsWith ids: [CKRecord.ID], completion: @escaping CompletionHandler<Void>) {
        let operation = CKModifyRecordsOperation(recordIDsToDelete: ids)
        operation.qualityOfService = .userInitiated
        operation.modifyRecordsCompletionBlock = { _, _, error in
            if let error = error {
                print("error:")
                print(error)
                if let err = error as? CKError, let time = err.retryAfterSeconds {
                    DispatchQueue.main.asyncAfter(deadline: .now() + time) {
                        self.remove(recordsWith: ids, completion: completion)
                    }
                } else {
                    completion(.failure(error))
                    print("CKDatabase.remove(_:_:) failed.")
                }
            } else {
                completion(.success(()))
                print("CKDatabase.remove(_:_:) succeeded.")
            }
        }
        self.add(operation)
    }
}


推荐答案

我认为代码正在删除执行查询方法中得到的内容。只是执行查询方法没有从所有现有记录中返回记录ID。

I think the code was deleting what it got from the perform query method. It's just that the perform query method was not returning the record ids from all the existing records.

这篇关于为什么要在CloudKit中批量删除记录的CKModifyRecordsOperation不删除记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆