iOS - Swift - 同步和异步

时间:2015-07-17 10:44:48

标签: ios swift asynchronous grand-central-dispatch

请帮助我解决这个问题 - 经过很多(不那么高效......)搜索之后,我不能单独解决这个问题。

我有以下方法:

showLoadingAnimation()

显示后台任务正在运行时的加载动画

hideLoadingAnimation()

在所有后台任务完成后立即隐藏加载动画

getUserFacebookData()

获取Facebook用户数据

uploadUserFacebookDataToServer()

将Facebook用户数据上传到服务器(并使用它们执行任务)。

我想要表演的内容:

  1. 显示加载动画: showLoadingAnimation()
  2. 从Facebook获取用户数据: getFacebookData()
    • 等到这些数据下载
  3. 下载Facebook用户数据后,立即将这些数据上传到服务器: uploadUserFacebookDataToServer()
    • 等待上传这些数据
  4. 隐藏加载动画: hideLoadingAnimation()
  5. 现在我的问题是,我不知道如何解决这个问题。我知道,我应该使用 sync 和/或 async 任务, GCD ...但我不知道怎么做,我可以找不到合适的指南。

    有人可以通过这些功能向我解释一下吗? 谢谢!

    更新:

    谢谢蔡志伟,这就是我所希望的答案。

    现在它似乎工作,调用顺序没问题, 但现在问题与开头一样:

    uploadUserFacebookDataToServer()
    

    不等到

    getUserFacebookData
    

    从Facebook下载用户数据,这就是为什么它无法处理从

    返回的必要数据的原因
    getUserFacebookData
    

    有什么想法吗?派遣有什么关系吗?

    更新2:

    根据您的要求,以下是功能。我希望,通过这些信息,您可以帮助我解决这个问题并理解整个过程。

    func getFacebookUserData(completionHandler: () -> Void)
    {
        println("getFacebookUserData")
    
        let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
        graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
    
            if ((error) != nil)
            {
                // Process error
                println("Error: \(error)")
            }
            else
            {
                let userID : NSString = result.valueForKey("id") as NSString!
    
                var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
                defaults.setObject(userID, forKey: "settings_facebookID")
                self.facebookID_fromSettings = userID
            }
        })
    

    func getObjectIDfromFacebookID(completionHandler: () -> Void)
    {
        println("getObjectIDfromFacebookID")
    
        var query = PFQuery(className:"users")
        query.whereKey("facebookID", equalTo:facebookID_fromSettings)
        println("getObjectIDfromFacebookID: facebookID: " + facebookID_fromSettings)
        query.findObjectsInBackgroundWithBlock {
            (objects: [AnyObject]?, error: NSError?) -> Void in
    
            if error == nil {
                // The find succeeded.
                    println("Successfully retrieved \(objects!.count) scores.")
                // Do something with the found objects
    
                if (objects!.count == 0) {
                    // New user, registering
                    println("New user, registering")
                }
                else
                {
                    //User is already regsitered, reading out objectID
                    println("User is already regsitered, reading out objectID")
                }
    
                if let objects = objects as? [PFObject] {
                    for object in objects {
                        println("objectID: " + object.objectId)
    
                        var objectID: String = object.objectId
                        println(objectID)
    
                        var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
                        defaults.setObject(objectID, forKey: "settings_objectID")
                    }
                }
    
            }
        }
        completionHandler()
    }
    

    所以第一个函数从FB服务器获取facebookID,但是这个过程需要时间,它不会立即给出结果。第二个函数应该可以处理这些数据,这就是为什么它应该“等待”直到第一个函数返回所请求的数据。

    我可以通过将这两个功能集合在一起来解决这个问题,但这是“不优雅”,我也想在项目的其他部分使用这个(同步/异步调度)方法,

    感谢您试图帮助我!

2 个答案:

答案 0 :(得分:2)

您可以使用完成处理程序

   func showLoadingAnimation() {
        self.getUserFacebookData({ () -> Void in
            self.uploadUserFacebookDataToServer({ () -> Void in
                self.hideLoadingAnimation()
            })
        })
    }

    func getUserFacebookData(completionHandler: () -> Void) {
        println("getUserFacebookData")
        completionHandler()
    }

    func uploadUserFacebookDataToServer(completionHandler: () -> Void) {
        println("uploadUserFacebookDataToServer")
        completionHandler()
    }

    func hideLoadingAnimation() {
        println("hideLoadingAnimation")
    }

调用showLoadingAnimation()后,其余部分将异步完成。

参考:https://developer.apple.com/library/ios/featuredarticles/Short_Practical_Guide_Blocks/

答案 1 :(得分:0)

[编辑] 使用dispatch_group_t 检查以下代码

第1步:showLoadingAnimation()

第2步:dispatch_group_t faceBookService = dispatch_group_create();

第3步:dispatch_group_async_enter(faceBookService,queue,^{ getUserFacebookData() // The below given line should be inside completion handler or after the above task has finished dispatch_group_leave(faceBookService); });

第4步:dispatch_group_async_enter(faceBookService,queue,^{ uploadUserFacebookDataToServer() // The below given line should be inside completion handler or after the above task has finished dispatch_group_leave(faceBookService); });

第5步:dispatch_group_notify(faceBookService,dispatch_get_main_queue(),^{ //Called after finishing both tasks. hideLoadingAnimation() });