快速执行函数

时间:2018-07-02 19:17:25

标签: swift

我有以下代码,该代码从Facebook登录名获取访问令牌,并将其作为“ accessToken”返回。获得访问令牌后,我希望将其在请求中传递给服务器,并以数组形式返回响应。

我遇到的问题是,在获取accessToken之前,对服务器的请求已执行。我已经研究了闭包语句,但看不到一种可以在不结束嵌套的情况下命令函数执行的方法。我不介意在这种情况下嵌套,但是将来如果我说5个函数,它将开始变得混乱。

我是否通过使用类和函数以最佳方式实现这一目标?通常,当我快速编写代码时,所有与viewController相关的代码都将包含在1个文件中,但是随着项目的扩大,我希望实现一种更加面向对象的方法,以使项目更易于管理。我怎样才能最好地做到这一点?

import Foundation
import UIKit

class registrationPage: UIViewController {

    @IBAction func facebookButton(_ sender: Any) {

        // Get the access token from facebook
        let accessToken = facebookLogin().login()

        // Get the users currency, langage and locale.
        let currency = Locale.current.currencyCode ?? "GBP"
        let language = Locale.current.languageCode ?? "GB"
        let region = Locale.current.regionCode ?? "GB"

        let params = "accessToken=\(accessToken)&currency=\(currency)&language=\(language)&region=\(region)"

        let resultArray = database().connect(endPoint: "loginfb.php?", params: "\(params)")

        print(resultArray)

    }
}

class facebookLogin {

    var response = ""

    func login(completion: (_ result: String) -> Void) {

     let loginManager = LoginManager()

     loginManager.logIn(readPermissions:[ReadPermission.publicProfile, ReadPermission.email], viewController: registrationPage() as UIViewController) {

    loginResult in switch loginResult {

    case .failed:
    self.response = "ERROR"

    case .cancelled:
    self.response = "ERROR"

    case .success:

        self.response = "\(String(describing: FBSDKAccessToken.current().tokenString!))"
        print(self.response)

    }
        }

        completion(self.response)
    }
}

1 个答案:

答案 0 :(得分:1)

loginManager.logIn是异步的,这就是为什么要关闭的原因。您可以同步调用,也可以按照您所说的使用嵌套闭包,其中一个调用下一​​个。

使let accessToken = facebookLogin().login()与DispatchGroup同步:

class facebookLogin {
    func login() -> String {
        let loginManager = LoginManager()

        var response = ""

        let group = DispatchGroup()
        group.enter() // loginManager.logIn

        loginManager.logIn(readPermissions:[ReadPermission.publicProfile, ReadPermission.email], viewController: registrationPage() as UIViewController) {

            loginResult in switch loginResult {                
            case .failed:
                self.response = "ERROR"

            case .cancelled:
                self.response = "ERROR"

            case .success:            
                self.response = "\(String(describing: FBSDKAccessToken.current().tokenString!))"
                print(self.response)

            }

            group.leave() // loginManager.logIn
        }

        group.wait()
        return response
    }
}

如果您不喜欢facebookLogin().login() { accessToken in ... }语法,可以将{ accessToken in ... }部分放入其自己的函数中

func callServer(accessToken: String) {
    // Get the users currency, langage and locale.
    let currency = Locale.current.currencyCode ?? "GBP"
    let language = Locale.current.languageCode ?? "GB"
    let region = Locale.current.regionCode ?? "GB"

    let params = "accessToken=\(accessToken)&currency=\(currency)&language=\(language)&region=\(region)"

    let resultArray = database().connect(endPoint: "loginfb.php?", params: "\(params)")

    print(resultArray)
}

并用

调用
@IBAction func facebookButton(_ sender: Any) {

    // Get the access token from facebook
    facebookLogin().login(completion: callServer(accessToken:))
}