Возврат строки из функции обработчика завершения URLSession Swift 3

Мне нужна эта функция (которая получает некоторые данные из базы данных), чтобы вернуть строку, но я не могу понять, как это сделать. Я нашел несколько похожих вопросов/решений, но я все еще пытаюсь реализовать правильное решение (я новичок в быстром)

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
}
}

Спасибо!


person m00912    schedule 22.06.2017    source источник
comment
Довольно близко к обману этого связанного вопроса.   -  person Michael Dautermann    schedule 22.06.2017


Ответы (1)


Ваш метод 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")
    }
}
person Brandon A    schedule 22.06.2017