如何在从 Swift 3 中的函数返回结果之前等待 URLSession 完成

Posted

技术标签:

【中文标题】如何在从 Swift 3 中的函数返回结果之前等待 URLSession 完成【英文标题】:how to wait for the URLSession to finish before returning the result from a function in Swift 3 【发布时间】:2017-08-05 20:54:00 【问题描述】:

您好,我有一个初学者问题,我在 Swift 3 中找不到好的解决方案。我希望有人能够帮忙。

我有以下代码将检查用户凭据是否有效。我希望它等待请求完成,然后返回真或假。现在它正在异步发送。

也欢迎对我检查 JSON 值的方式进行任何改进。

func CheckUsernamePassword(username :String ,code:String )-> bool 

    var validCredentials = false


    let urlString = "\(self.baseurl)/accounts/validateusernamepassword.json?username=\(username)&password=\(code)&api_key=\(self.api_key)"

    let url = URL(string: urlString)
    URLSession.shared.dataTask(with:url!)  (data, response, error) in
        if error != nil 
            print("Error URLSession : \(error!)")
            validCredentials = false
         else 
            do 
                let parsedData = try JSONSerialization.jsonObject(with: data!, options: []) as! [String:Any]

                if parsedData["validated"] != nil 
                    if "\(parsedData["validated"]!)" == "1" 
                        print("Login credentials are correct")
                        validCredentials = true             
                    else 
                        print("Login credentials are not correct")
                        print("\(parsedData["validated"]!)")
                        print("\(parsedData["message"]!)")
                        validCredentials = false
                    
                else
                    print("Json Parse error: \(parsedData)")
                    validCredentials = false
                
             catch let error as NSError 
                print("Error Parsing Json \(error)" )
                validCredentials = false
            
        

        .resume()
    return validCredentials          

【问题讨论】:

【参考方案1】:

您不能从异步任务中返回某些内容作为返回值。

不要等待,使用完成处理程序:

将方法的签名(名称应该以小写字母开头)替换为

func checkUsernamePassword(username: String, code: String, completion: @escaping (Bool)->() ) 

删除var validCredentials = falsereturn validCredentials这行

将所有出现的validCredentials = false 替换为completion(false)validCredentials = truecompletion(true)

调用方法

checkUsernamePassword(username: "Foo", code: "Baz")  isValid in
    print(isValid)
    // do something with the returned Bool
    DispatchQueue.main.async 
       // update UI
    

【讨论】:

我尝试了 vadian 建议的方式,该功能确实有效,但有一个小问题,当我调用该方法时,我执行 if 语句以查看其真假并更改文本标签屏幕。但更新屏幕大约需要 5 - 7 秒。我怎样才能改变性能 你要更新主线程的UI,我更新了答案。 感谢您的回答。它帮助了我.. 但是我怎样才能将结果传递回启动器视图控制器。以下代码与一些隐式声明有问题if let presenter = presenting as? ViewController if(self.correct) presenter.bvalue=false 请建议。 macOS 还是 ios(好像是 macOS)?在 macOS 中,您可以访问 presenting 视图控制器,因此您可以直接调用方法。 @vadian 它的 macOS...我不明白.. 你能给我一个例子吗,拜托。

以上是关于如何在从 Swift 3 中的函数返回结果之前等待 URLSession 完成的主要内容,如果未能解决你的问题,请参考以下文章

在从函数返回之前等待 Firebase 加载

如何让任务在 Swift 3 中等待完成

如何在执行函数之前等待 Swift 中的变量? (迅速)

如何确保在从 Mongoose 中的函数返回之前执行异步调用?

函数等待返回直到 $.getJSON 完成

useEffect 等待异步函数的结果