如何将变量值传递给URLSession async外部 - swift 3

时间:2017-08-23 09:48:03

标签: swift asynchronous

我有这段代码:

let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
    if error != nil {
        print(error!)
        return    
    }    
    do {        
        let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

        if let parseJSON = json {        
            let getDetail = parseJSON["detail"] as? String

            returnDetail = getDetail!.base64Decoded()        
        } // parse json end    
    } // do end                
    catch {         
        print(error)    
    }    
} // let task end
之前已经定义了

returnDetail。我做了一些事情来将returnDetail值设置为getDetail!.base64Decoded(),但它仅适用于let task = ...

如何将其传递到外部范围?

3 个答案:

答案 0 :(得分:3)

您有几种方法可以解决从异步函数内部返回值的问题。其中之一是将异步网络调用包装在函数中,并使其返回completionHandler。

一些一般性建议:除非您100%确定您的可选值不是nil,否则请勿使用强制解包。对于网络请求,即使没有错误,data也可以为零,因此请勿强制解包data,请使用if letguard let进行安全解包。解析JSON值时不要在Swift中使用.mutableContainers,因为它没有效果。解析的JSON对象的可变性通过使用letvar关键字来声明保存它的变量来确定。也不要使用NSDictionary,使用其原生的Swift对应词,Dictionary([String:Any]Dictionary<String,Any>类型的简写)。

func getDetail(withRequest request: URLRequest, withCompletion completion: @escaping (String?, Error?) -> Void) {
    let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
        if error != nil {
            completion(nil, error)
            return    
        }    
        else if let data = data {
            do {        
                guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] else {completion(nil, nil);return}      
                guard let details = json["detail"] as? String else {completion(nil, nil);return}
                completion(details, nil)        
            }                  
            catch {         
                completion(nil, error)  
            }
        }   
    }
    task.resume()
}

然后你可以通过

调用这个函数
getDetail(withRequest: request, withCompletion: { detail, error in
    if error != nil {
        //handle error
    } else if detail = detail {
        //You can use detail here
    }
})

答案 1 :(得分:0)

我建议使用完成处理程序。

func foo(withCompletion completion: (String?, Error?) -> Void) {
    let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
        if error != nil {
            completion(nil, error)
            return    
        }    

        do {        
            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

            if let parseJSON = json {        
                let details = parseJSON["detail"] as? String

                completion(details, nil)        
            } // parse json end    
        } // do end                
        catch {         
            completion(nil, error)  
        }   
    } // let task end
}

答案 2 :(得分:0)

我认为,当getDetail有数据时,你使用Swift的CallBack(Clourse)来返回数据。