Cha*_*nce 5 uikit async-await swift
晚安,抱歉我的英语不好,我正在学习 swift async/await、任务和调度。好吧,我得到了执行谷歌登录的代码块有几个回调,所以我尝试将整个方法转换为异步。
self.navigationController?.dismiss(animated: true, completion: nil)我的问题是,当我调用重构方法并应用 async/await 时,我在使用断点执行时收到错误Thread 14: "Call must be made on main thread"。
我明白他的意思,但是如何在主线程上运行 .dimiss ?我说我已经不在主线了?它是从什么时候出来的,我不太明白。
这是我的带有链式回调的代码,它工作正常。
guard let clientId = FirebaseApp.app()?.options.clientID else {
print("failed get clientId google signin")
return
}
let config = GIDConfiguration(clientID: clientId)
GIDSignIn.sharedInstance.signIn(with: config, presenting: self, callback: { [weak self] authResult, error in
guard let strongSelf = self else {
return
}
guard authResult != nil, error == nil else {
if let error = error {
print("failed login with google sign in \(error)")
}
return
}
guard let authentication = authResult?.authentication,
let idToken = authentication.idToken else {
return
}
guard let email = authResult?.profile?.email,
let firstName = authResult?.profile?.givenName,
let lastName = authResult?.profile?.familyName else {
return;
}
DatabaseManager.shared.userExists(with: email, completion: { exists in
if !exists {
//insert database
let chatUser = ChatAppUser(firtName: firstName, lastName: lastName, emailAddress: email)
DatabaseManager.shared.insertUser(with: chatUser, completion: { success in
if success {
//upload image
if ((authResult?.profile?.hasImage) != nil) {
guard let url = authResult?.profile?.imageURL(withDimension: 200) else {
return
}
URLSession.shared.dataTask(with: url, completionHandler: {data, _, _ in
guard let data = data else {
return
}
let fileName = chatUser.profilePictureFileName
StorageManager.shared.uploadProfilePicture(with: data, fileName: fileName, completion: { result in
switch result {
case .success (let downloadUrl):
UserDefaults.standard.set(downloadUrl, forKey: "profile_picture_url")
print(downloadUrl)
case .failure(let error):
print("Storage manager error: \(error)")
}
})
}).resume()
}
}
})
}
})
let credentials = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: authentication.accessToken)
Auth.auth().signIn(with: credentials, completion: {authResult, error in
guard authResult != nil, error == nil else {
if let error = error {
print("google credential login failed, MFA may be needed \(error)")
}
return;
}
print("successFully logged user in")
strongSelf.navigationController?.dismiss(animated: true, completion: nil)
})
})
Run Code Online (Sandbox Code Playgroud)
这是我应用了 async/await 的代码。
guard let clientId = FirebaseApp.app()?.options.clientID else {
print("failed get clientId google signin")
return
}
let config = GIDConfiguration(clientID: clientId)
do {
let resultSignin = try await GoogleManager.shared.googleSignin(config: config, presenting: self)
switch resultSignin {
case .success(let autheResult):
let authentication = autheResult.authentication
guard let idToken = authentication.idToken else {
break
}
//function authentication
guard let email = autheResult.profile?.email,
let firstName = autheResult.profile?.givenName,
let lastName = autheResult.profile?.familyName else {
break
}
let ifExist = try await DatabaseManager.shared.userExists(with: email)
if ifExist {
let chatUser = ChatAppUser(firtName: firstName, lastName: lastName, emailAddress: email)
let resultInsert = try await DatabaseManager.shared.insertUser(with: chatUser)
if resultInsert {
if autheResult.profile?.hasImage != nil {
guard let url = autheResult.profile?.imageURL(withDimension: 200) else{
break
}
let dataPicture = await ApiManager.shared.getData(url: url)
guard let dataPicture = dataPicture else {
break
}
let fileName = chatUser.profilePictureFileName
let resultUpload = try await StorageManager.shared.uploadProfilePicture(with: dataPicture, fileName: fileName)
switch resultUpload {
case .success (let downloadUrl):
UserDefaults.standard.set(downloadUrl, forKey: "profile_picture_url")
print(downloadUrl)
break
case .failure(let error):
print("Storage manager error: \(error)")
alertUserLoginError(message: "Storage manager error: \(error)")
break
}
}
}
}
let credentials = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: authentication.accessToken)
let authResult = try await Auth.auth().signIn(with: credentials)
print("Logged In user: \(authResult.user)")
self.navigationController?.dismiss(animated: true, completion: nil)
break
case .failure(let error):
alertUserLoginError(message: "Error: \(error)")
break
}
}catch let error as NSError {
print("Try catch error: \(error)")
alertUserLoginError(message: "Try catch error: \(error)")
}
Run Code Online (Sandbox Code Playgroud)
谷歌登录
final class GoogleManager {
static let shared = GoogleManager()
private let googleInstance = GIDSignIn.sharedInstance
}
extension GoogleManager {
public func googleSignin(config: GIDConfiguration, presenting: UIViewController, completion: @escaping (Result<GIDGoogleUser,Error>) -> Void){
googleInstance.signIn(with: config, presenting: presenting, callback: { authResult, error in
guard authResult != nil, error == nil else {
completion(.failure(error!))
return
}
completion(.success(authResult!))
})
}
public func googleSignin(config: GIDConfiguration, presenting: UIViewController) async throws -> (Result<GIDGoogleUser, Error>) {
await withCheckedContinuation { continuation in
googleSignin(config: config, presenting: presenting, completion: { result in
continuation.resume(returning: result)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪:
Main Thread Checker: UI API called on a background thread: -[UIViewController navigationController]
PID: 426, TID: 18401, Thread name: (none), Queue name: Swift global concurrent queue, QoS: 25
Backtrace:
4 Messenger 0x0000000102dc0360 $s9Messenger19LoginViewControllerC19googleButtonClicked022_498C1017229A4D9B461B7L9B38EF23C9LLyyYaFTQ5_
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5073 次 |
| 最近记录: |