我有以下代码,该代码从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)¤cy=\(currency)&language=\(language)®ion=\(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)
}
}
答案 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)¤cy=\(currency)&language=\(language)®ion=\(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:))
}