gpt4 book ai didi

ios - 为什么CloudKit中批量删除记录的CKModifyRecordsOperation没有删除记录?

转载 作者:行者123 更新时间:2023-12-01 16:01:15 24 4
gpt4 key购买 nike

我有代码可以从 CloudKit 中的私有(private)数据库中批量删除记录,但它不起作用。 (我还注意到我保存的记录没有保留。)我使用的是实际的 iPhone 8,并且带有我个人使用的实际 Apple ID,而不是开发者帐户。我使用 iPhone 8 模拟器得到了相同的结果。当我使用 iPhone 8 模拟器使用与我的开发者帐户相同的 Apple ID 登录 iCloud 时,没有出现此问题。

在这篇文章的答案没有给我解决方案之后,我认为这个问题最重要的是,当我使用非我的开发者帐户的 Apple ID 时,就会出现此问题。我在两个不同的 Apple ID(不是我的开发者帐户)上进行了尝试。这可能是我在某个地方忽略的设置吗?

stackoverflow 上的类似帖子都没有解决这个问题。

看起来代码应该删除的一些记录实际上被删除了,但有些却没有。当我再次运行代码时,仍然存在记录,但数量比以前少了大约一条。

这是我的代码:

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)

}

}

}

}

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

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

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

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() 时...

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

}

}

}

}

}

我进入调试窗口:

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__>)

这是我最新的代码,但仍然不起作用:

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

最佳答案

有时 CloudKit 会向您抛出不同的错误,因此您必须确保处理它们,并在错误包含 retryAfterSeconds 时再次触发调用。在这里,使用 CKDatabase 的包装方法来轻松处理错误。调用任何 CloudKit API 时,请确保将您的请求分批处理为较小的 block (例如,每个 block 100 个)。

extension CKDatabase {
func remove(
recordsWith ids: [CKRecord.ID],
completion: @escaping (Result<Void, Error>) -> Void
) {
let operation = CKModifyRecordsOperation(recordIDsToDelete: ids)
operation.qualityOfService = .userInitiated
operation.modifyRecordsCompletionBlock = { _, _, error in
if let error = 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))
}
} else {
completion(.success(()))
}
}
self.add(operation)
}
}

关于ios - 为什么CloudKit中批量删除记录的CKModifyRecordsOperation没有删除记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61162395/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com