嵌套 Cloudkit 查询未按正确顺序打印
Posted
技术标签:
【中文标题】嵌套 Cloudkit 查询未按正确顺序打印【英文标题】:Nested Cloudkit queries not printing in the right order 【发布时间】:2020-09-15 15:35:24 【问题描述】:我的代码打印顺序不正确。我认为这是我使用 dispatch to main 的方式的问题。我想传递一个老板ID。找到具有该 ID 的用户,然后获取他们的订阅老板数组。对于该数组中的每个 ID,查询该用户并返回该用户 screenName。将这些屏幕名称附加到 userArray。之后完成 GetBossSubs 函数并返回 userArray(screenNames 数组)。
现在.onAppear
的结果在.onAppear 中的函数实际完成之前运行。 User Appended
在Found TestUserName
之前打印
static func getBossSubs(bossID: String, completion: @escaping (Result<UserNames, Error>) ->
())
let pred = NSPredicate(format: "uniqueID = %@", bossID)
let sort = NSSortDescriptor(key: "creationDate", ascending: false)
let query = CKQuery(recordType: RecordType.Users, predicate: pred)
query.sortDescriptors = [sort]
let operation = CKQueryOperation(query: query)
operation.desiredKeys = ["subscribedBosses"]
operation.resultsLimit = 50
operation.recordFetchedBlock = record in
DispatchQueue.main.async
guard let subs = record["subscribedBosses"] as? [String] else
print("Error at screenName")
completion(.failure(CloudKitHelperError.castFailure))
return
let userArray = UserNames() //Error that it should be a LET is here.
for boss in subs
CloudKitHelper.getBossScreenName(bossID: boss) (result) in
switch result
case .success(let name):
userArray.names.append(name) //works fine
print("Found \(userArray.names)") //Prints a name
case .failure(let er):
completion(.failure(er))
print("does this run?") // Only runs if No Name
completion(.success(userArray)) // contains no name or doesn't run?
operation.queryCompletionBlock = (_, err) in
DispatchQueue.main.async
if let err = err
completion(.failure(err))
return
CKContainer.default().publicCloudDatabase.add(operation)
我这样称呼代码:
.onAppear
// MARK: - fetch from CloudKit
self.userList.names = []
let myUserID = UserDefaults.standard.string(forKey: self.signInWithAppleManager.userIdentifierKey)!
// get my subs projects
CloudKitHelper.getBossSubs(bossID: myUserID) (results) in
switch results
case .success(let user):
print("Users appended")
self.userList.names = user.names
case .failure(let er):
print(er.localizedDescription)
【问题讨论】:
【参考方案1】:这是因为您在另一个异步函数中运行了一个异步函数。
// this just *starts* a series of asynchronous functions, `result` is not yet available
for boss in subs
CloudKitHelper.getBossScreenName(bossID: boss) result in
switch result
case .success(let name):
userArray.names.append(name) // works fine
print("Found \(userArray.names)") // Prints a name
case .failure(let er):
completion(.failure(er))
// this will run before any `CloudKitHelper.getBossScreenName` finishes
completion(.success(userArray))
一种可能的解决方案可能是检查所有CloudKitHelper.getBossScreenName
函数是否完成(例如,通过检查userArray
的大小),然后才返回完成:
for boss in subs
CloudKitHelper.getBossScreenName(bossID: boss) result in
switch result
case .success(let name):
userArray.names.append(name)
if userArray.names.count == subs.count
completion(.success(userArray)) // complete only when all functions finish
case .failure(let er):
completion(.failure(er))
// do not call completion here, wait for all functions to finish
// completion(.success(userArray))
【讨论】:
所以我需要在 for 循环内部添加第二个完成(.success())?它也被附加了,所以我想我需要看看之前的计数 + subs.count == 当前的计数。 for 循环下方的完成在任何CloudKitHelper.getBossScreenName
完成之前触发。您需要按照上面的示例移动它。你的情况应该只有一个completion(.success())
。
哦,这就是为什么你让它等于潜艇的数量!以上是关于嵌套 Cloudkit 查询未按正确顺序打印的主要内容,如果未能解决你的问题,请参考以下文章