首页 > 解决方案 > Swift Alamofire 异步问题

问题描述

新来的 swift 在这里。

我正在尝试在另一个 AF.request 调用中进行 AF.request 调用,一切正常。

问题是fetchAllUsers()在所有内容加载后都会被调用。因此,我必须刷新页面才能执行,而不是立即获取所有用户fetchAllUsers()

我认为使用闭包可以避免这个问题,但它仍然在发生。

难道我做错了什么?

func fetchAllUsers(completionHandler: @escaping ([User]) -> Void) {
        let allUsersUrl = baseUrl + "users/"
        let headers: HTTPHeaders = [
            .authorization(bearerToken: NetworkManager.authToken)
        ]
        
        if let url = URL(string: allUsersUrl) {
            AF.request(url, headers: headers).responseDecodable(of: [User].self) { response in
                if let users = response.value {
                    completionHandler(users)
                } else {
                    print("Users is empty")
                }
            }
        } else {
            print("URL error")
        }
    }

 func login(param: [String:String], completionHandler: @escaping (Int) -> Void) {
    let loginUrl = baseUrl + "auth/login"        
    
    // Sets the Logged In User
    AF.request(loginUrl, method: .post, parameters: param, encoding: JSONEncoding.default, headers: nil).responseString { response in
        if let data = response.data {
            let authTokenString = String(decoding: data, as:UTF8.self).components(separatedBy: " ")
            
            // Sets the authentication token
            NetworkManager.authToken = authTokenString[1]
            
            self.fetchAllUsers { users in
                for user in users {
                    if param["username"] == user.username {
                        HomeViewModel.loggedInUser = user
                    }
                }
            }
                            
            completionHandler(response.response!.statusCode)
        }
    }
}

标签: swiftalamofire

解决方案


将主函数的完成处理程序和状态代码传递给 fetchAllUsers 并在它自己的完成处理程序之后调用它

completionHandler(response.response!.statusCode)在self.fetchAllUsers 关闭之前执行,因为它正在等待 api 响应完成。completionHandler(response.response!.statusCode)在执行之前破坏了self.fetchAllUsers 闭包,所以我在 self.fetchAllUsers 关闭之后调用了 completionHandler(response.response!.statusCode)

 completionHandler(users)
 mainCompletion(statusCode)  

完整的代码工作如下

func fetchAllUsers(statusCode:Int, mainCompletion: @escaping (Int) -> Void, completionHandler: @escaping ([User]) -> Void) {
        let allUsersUrl = baseUrl + "users/"
        let headers: HTTPHeaders = [
            .authorization(bearerToken: NetworkManager.authToken)
        ]
    
        if let url = URL(string: allUsersUrl) {
            AF.request(url, headers: headers).responseDecodable(of: [User].self) { response in
                if let users = response.value {
                    completionHandler(users)
                    mainCompletion(statusCode)
                } else {
                        print("Users is empty")
                }
            }
        } else {
            print("URL error")
        }
    }

func login(param: [String:String], completionHandler: @escaping (Int) -> Void) {
    let loginUrl = baseUrl + "auth/login"        

    // Sets the Logged In User
    AF.request(loginUrl, method: .post, parameters: param, encoding: JSONEncoding.default, headers: nil).responseString { response in
        if let data = response.data {
            let authTokenString = String(decoding: data, as:UTF8.self).components(separatedBy: " ")
        
            // Sets the authentication token
            NetworkManager.authToken = authTokenString[1]
        
            self.fetchAllUsers(statusCode: response.response!.statusCode, mainCompletion: completionHandler) { users in
                for user in users {
                    if param["username"] == user.username {
                        HomeViewModel.loggedInUser = user
                    }
                }
            }
                        
            
        }
    }
}

推荐阅读