Asynchronous CloudKit完成处理程序和调度同步问题
我对云工具包有以下查询Asynchronous CloudKit完成处理程序和调度同步问题,asynchronous,cloudkit,completionhandler,Asynchronous,Cloudkit,Completionhandler,我对云工具包有以下查询 func cloudKitManageUserPublicTable (typeOfOperation: Int, encriptedBabyName: String?, encriptedOllyKey:String?, result: (error: NSError?, userHasBeenFound: Bool?, ollYKeyHasBeenFound: Bool?, encriptedBabyNameFound: String?) -> Void){
func cloudKitManageUserPublicTable (typeOfOperation: Int, encriptedBabyName: String?, encriptedOllyKey:String?, result: (error: NSError?, userHasBeenFound: Bool?, ollYKeyHasBeenFound: Bool?, encriptedBabyNameFound: String?) -> Void){
// OPERATION TYPES
// 1 - search for user and add, link or update a key
// 2 - search for user and check he has a key
// 3 - search for a key
// 4 - search for user and add a default one if has not been found
print("cloudKitManageUserPublicTable - operation \(typeOfOperation)")
var recordCounter = 0
var publicUserRecord = CKRecord(recordType: "PublicUsers")
let useriCloudID = NSUserDefaults.standardUserDefaults().objectForKey("useriCloudID") as! String
var predicate = NSPredicate()
switch typeOfOperation {
case 1:
predicate = NSPredicate(format: "useriCloudID == %@", useriCloudID)
case 2:
predicate = NSPredicate(format: "useriCloudID == %@", useriCloudID)
case 3:
predicate = NSPredicate(format: "encriptedOllyKey == %@", encriptedOllyKey!)
default:
print("no scenarios")
}
let cloudKitQuery = CKQuery(recordType: "PublicUsers", predicate: predicate)
let queryOperation = CKQueryOperation(query: cloudKitQuery)
let operationQueue = NSOperationQueue()
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase;
queryOperation.database = publicDatabase
queryOperation.recordFetchedBlock = { (record : CKRecord) -> Void in
publicUserRecord = record
recordCounter += 1
}
queryOperation.queryCompletionBlock = { (cursor: CKQueryCursor?, error: NSError?) -> Void in
print("cloudKitManageUserPublicTable - # of record found - \(recordCounter)")
if error != nil
{
// ERROR STOP
print("cloudKitManageUserPublicTable - error - \(error)")
result(error: error, userHasBeenFound: nil, ollYKeyHasBeenFound: nil, encriptedBabyNameFound: nil)
}
else
{
switch typeOfOperation {
case 1:
// KEY FOUND, UPDATE
print("cloudKitManageUserPublicTable - search for user and add or update a key")
publicUserRecord["encriptedBabyName"] = encriptedBabyName!
publicUserRecord["encriptedOllyKey"] = encriptedOllyKey!
publicUserRecord["hasKey"] = true
publicDatabase.saveRecord(publicUserRecord) { (CKRecord: CKRecord?, error: NSError?) -> Void in
if error != nil
{
print("cloudKitManageUserPublicTable - creating key - UPDATE error \(error)")
result(error: error, userHasBeenFound: nil, ollYKeyHasBeenFound: nil, encriptedBabyNameFound: nil)
}
else
{
print("cloudKitManageUserPublicTable - creating key - UPDATE OK")
result(error: error, userHasBeenFound: nil, ollYKeyHasBeenFound: true, encriptedBabyNameFound: nil)
}
}
case 2:
print("cloudKitManageUserPublicTable - search for user and check it has a key")
if publicUserRecord.objectForKey("hasKey") as? Bool == false
{
print("cloudKitManageUserPublicTable - user do not have a key")
result(error: nil, userHasBeenFound: nil, ollYKeyHasBeenFound: false, encriptedBabyNameFound: nil)
}
else
{
print("cloudKitManageUserPublicTable - user has a key")
result(error: nil, userHasBeenFound: nil, ollYKeyHasBeenFound: true, encriptedBabyNameFound: nil)
}
case 3:
if recordCounter == 0
{
print("cloudKitManageUserPublicTable - no record has this key")
result(error: nil, userHasBeenFound: nil, ollYKeyHasBeenFound: false, encriptedBabyNameFound: nil)
}
else
{
print("cloudKitManageUserPublicTable - \(recordCounter) records have this key")
result(error: nil, userHasBeenFound: nil, ollYKeyHasBeenFound: true, encriptedBabyNameFound: nil)
}
case 4:
if recordCounter == 0
{
// NO USER FOUND, CREATE
print("cloudKitManageUserPublicTable - search for user and add a default one if has not been found")
// publicUserRecord["encriptedBabyName"] = ""
// publicUserRecord["encriptedOllyKey"] = ""
publicUserRecord["hasKey"] = false
publicUserRecord["useriCloudID"] = useriCloudID
publicDatabase.saveRecord(publicUserRecord) { (CKRecord: CKRecord?, error: NSError?) -> Void in
dispatch_async(dispatch_get_main_queue()) {
if error != nil
{
print("cloudKitManageUserPublicTable - no user - CREATE error \(error)")
result(error: nil, userHasBeenFound: false, ollYKeyHasBeenFound: nil, encriptedBabyNameFound: nil)
}
else
{
print("cloudKitManageUserPublicTable - no user found - CREATE ok")
result(error: nil, userHasBeenFound: false, ollYKeyHasBeenFound: nil, encriptedBabyNameFound: nil)
}
}
}
}
else
{
// USER FOUND - DO NOTHING
print("cloudKitManageUserPublicTable - user exists, do nothing for now")
result(error: nil, userHasBeenFound: true, ollYKeyHasBeenFound: nil, encriptedBabyNameFound: nil)
}
default:
print("no scenarios")
}
}
}
operationQueue.addOperation(queryOperation)
}
上面的方法第一次被下面的方法调用,我等待完成处理程序返回,然后第二次调用上面的方法,然后验证publicUserRecord[“hasKey”]=false
是否设置为false
但我的问题是。当我第二次调用该方法来验证publicUserRecord[“hasKey”]
时,它返回尚未保存任何内容。如果我随后稍等片刻,并调用该方法第三次验证publicUserRecord[“hasKey”]
,那么它会找到并验证它
因为我在做同样的调用,并且结果已经保存在第一个调用中,所以苹果服务器似乎有点滞后,或者我没有正确使用完成处理程序、dispatch\u async、dispatch\u sync?有什么想法吗
func manageUserPublicTable(){
tryAgainButtonOutlet.enabled = false
let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
spinningActivity.labelText = "Talking to Apple Servers"
spinningActivity.detailsLabelText = "Creating user credentials..."
cloudKitManageUserPublicTable(1) { (error, userExists) -> Void in
dispatch_sync(dispatch_get_main_queue()) {
if error != nil
{
spinningActivity.hide(true)
// let user try again
let optionMenu = UIAlertController(title: nil, message: "Are you all set to upload this record?!", preferredStyle: .ActionSheet)
let tryAgain = UIAlertAction(title: "Try again", style: .Default, handler: {
(alert: UIAlertAction!) -> Void in
self.tryAgainButtonOutlet.enabled = true
})
let cancelAction = UIAlertAction(title: "Not yet...", style: .Cancel, handler: {
(alert: UIAlertAction!) -> Void in
self.tryAgainButtonOutlet.enabled = true
})
optionMenu.addAction(tryAgain)
optionMenu.addAction(cancelAction)
if(isIPad()) {
optionMenu.popoverPresentationController!.permittedArrowDirections = UIPopoverArrowDirection()
optionMenu.popoverPresentationController!.sourceView = self.view
optionMenu.popoverPresentationController!.sourceRect = CGRectMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0, 1.0, 1.0)
}
self.presentViewController(optionMenu, animated: true, completion: nil)
}
else
{
spinningActivity.hide(true)
self.manageEncriptedKey()
}
}
}
}
实际上,在保存数据和检索数据之间可能会有一段时间。没有具体说明这可能需要多长时间。通常不到几秒钟 因此,你必须让你的应用程序逻辑,使它不关心这一点。您已经保存了该记录,因此您的应用程序已经知道该记录的内容。您可以从回调传递记录,这样就不必再次查询它
另一种想法。你的功能对我来说有点大。1功能中的功能太多。这使得阅读变得困难。理想情况下,函数只能做一件事。谢谢Edwin,这回答了问题。