从URLSession完成处理程序函数中返回字符串 Swift 3

3

我需要这个函数(从数据库中获取数据)返回一个字符串,但我遇到了困难。我找到了一些类似的问题/解决方案,但我仍然难以实现一个正确的解决方案(我对Swift还比较陌生)。

class Helper{
static func pReq(jsonURL : String, col : String) -> String {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    let url  = URL(string: jsonURL)!
    let request = URLRequest(url: url)
    var string = ""

    let downloadTask = session.dataTask(with: request, completionHandler: {(data, response, error) in
        if(error == nil){ 
            print("data = \(String(describing: data))")
            do{
                print(jsonURL)
                let dataDownloadedAsJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:AnyObject]
                print("dataDownloadedAsJson = \(dataDownloadedAsJson)")
                do{

                    if(dataDownloadedAsJson[col] as? String != nil){
                        string = (dataDownloadedAsJson[col] as? String)!

                    }
                }
            }
            catch{
            }
        }
        else{
            print("Error downloading data. Error = \(String(describing: error))")
        }
    })
    downloadTask.resume()
    return string
}
}

谢谢!


非常接近于这个相关问题的重复(https://dev59.com/rGAf5IYBdhLWcg3wbSUi)。 - Michael Dautermann
1个回答

4
你的session.dataTask(with:方法是异步的。这意味着它将在“后台”执行,并在完成调用后通知您。它会在"{}"内部,即session.dataTask(with:部分下面的块中通知您。看起来,您正在处理接收到的JSON并将其格式化为您想从此函数返回的字符串。 但是你在底部调用了return string,而此时你的调用尚未完成,所以你将返回""什么也没有。你真正需要做的是不要从函数中返回任何东西,而是使用完成块:

1)在文件顶部声明:

typealias StringCompletion      = (_ success: Bool, _ string: String) -> Void

2) 修改您的函数,以接受一个参数来表示完成情况

// This
static func pReq(jsonURL : String, col : String) -> String

// Becomes This
static func pReq(jsonURL : String, col : String, completion: @escaping StringCompletion)

3) 在你的函数内部调用完成并返回一个Bool来表示它是一个成功的调用,并将string一起传回。

class Helper{
static func pReq(jsonURL : String, col : String, completion: @escaping StringCompletion) {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    let url  = URL(string: jsonURL)!
    let request = URLRequest(url: url)
    var string = ""

    let downloadTask = session.dataTask(with: request, completionHandler: {(data, response, error) in
        if(error == nil){ 
            print("data = \(String(describing: data))")
            do{
                print(jsonURL)
                let dataDownloadedAsJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:AnyObject]
                print("dataDownloadedAsJson = \(dataDownloadedAsJson)")
                do{

                    if(dataDownloadedAsJson[col] as? String != nil){
                        string = (dataDownloadedAsJson[col] as? String)! 
                        completion(true, string)
                    }
                }
                catch { completion(false, string) }
            }
            catch{
                completion(false, string)
            }
        }
        else{
            print("Error downloading data. Error = \(String(describing: error))")       
            completion(false, string)
        }
    })
    downloadTask.resume()
}
}

4) 用法:

Helper().pReq(jsonURL: jsonURL, col: col) { (success, string) in
    if success {
        print("Success: \(string)")
    }
    else {
        print("Failure: Unable To Get String")
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接