Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
642 views
in Technique[技术] by (71.8m points)

asynchronous - how to pass variable value to outside of URLSession async - swift 3

I have this code :

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 has been defined previously. I did anything to set returnDetail value to getDetail!.base64Decoded() but it only works inside let task = ...

How can I pass it to the outer scope?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have several methods to tackle the issue of returning a value from inside an asynchronous function. One of them is to wrap the asynchronous network call inside a function and make it return a completionHandler.

Some general advice: don't use force unwrapping unless you are 100% sure that your optional value won't be nil. With network requests, the data can be nil even if there's no error, so never force unwrap data, use safe unwrapping with if let or guard let. Don't use .mutableContainers in Swift when parsing a JSON value, since it has no effect. The mutability of the parsed JSON object is decided by using the let or var keyword to declare the variable holding it. Also don't use NSDictionary, use its native Swift counterpart, Dictionary ([String:Any] is a shorthand for the type 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()
}

Then you can call this function by

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...