Swift 3 中带有异步调用的 CompletionHandler

Posted

技术标签:

【中文标题】Swift 3 中带有异步调用的 CompletionHandler【英文标题】:CompletionHandler with Async call in Swift 3 【发布时间】:2016-11-24 09:39:39 【问题描述】:

我想从方法(使用异步调用)返回一个数组 (arr)。我在方法中实现了completionHandler,但是我不能使用我的方法来获取我的数组:Cast from '(@escaping ((Array<Any>) -> Void)) -> ()' to unrelated type '[[String : Any]]' always fails

我该如何解决这个问题?

这是我的代码:

func dataWithURL(completion: @escaping ((_ result:Array<Any>) -> Void)) 
    let urlString = "https://api.unsplash.com/photos/?client_id=71ad401443f49f22556bb6a31c09d62429323491356d2e829b23f8958fd108c4"
    let url = URL(string: urlString)!
    let urlRequest = URLRequest(url: url)
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    var arr = [[String:String]]()
    let task = session.dataTask(with: urlRequest, completionHandler:  (data, response, error) in
        // do stuff with response, data & error here
        if let statusesArray = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [[String: Any]] 
            for item in statusesArray! 
                let photos = item["urls"] as? [String: Any]
                let photo = photos?["small"] as? String
                let myDictionary = [
                    "name": "test",
                    "imageURL": photo]
                arr.append(myDictionary as! [String : String])
            
            print(arr)
            completion(arr)
        
    )

    task.resume()

当我想得到我的数组时:

lazy var photos: [Photo] = 

    var photos = [Photo]()

// HERE THE ERROR APPEARS
guard let data = self.dataWithURL as? [[String: Any]] else  return photos 
    for info in data 
        let photo = Photo(info: info)
        photos.append(photo)
    
    return photos
()

【问题讨论】:

我觉得你应该先搜索一下如何调用函数,如何使用闭包,如何使用闭包作为完成块。 【参考方案1】:

dataWithURL 接受回调(完成处理程序),因此您只能在回调中访问结果。

self.dataWithURL  result in
//do stuff with the result
 

但是,上面代码的问题是您期望 dataWithURL 返回它没有返回的结果。它返回 void。

另一个问题是您试图将 dataWithURL 的结果用于属性。访问惰性 var photos 的调用不会产生任何结果(至少在第一次调用时),因为调用 dataWithURL 是异步的(立即返回)。

【讨论】:

【参考方案2】:

你似乎也是 xcode_Dev 昨天问了this 问题。

我对这个问题写了评论:

你不能从包含异步任务的函数(或计算变量)返回一些东西

这仍然是真的。

dataWithURL 是一个异步函数,它不返回任何内容,但您必须传递一个在返回时调用的闭包。

首先,数组显然是[[String:String]](带有字符串键和字符串值的字典数组),所以使用更多未指定的类型[Any] 非常愚蠢

func dataWithURL(completion: @escaping ([[String:String]]) -> Void) 

在 Swift 3 中,仅在声明中指定类型,不带下划线和参数标签。


你必须这样调用函数:

dataWithURL  result in
    for item in result  // the compiler knows the type
        print(item["name"], item["imageURL"])
    

再一次:dataWithURL 没有返回值。稍后会调用闭包。

【讨论】:

以上是关于Swift 3 中带有异步调用的 CompletionHandler的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中带有自定义 TableViewCell 的核心数据图像

如何在 Swift 中关闭 ViewController?

swift Swift中带有协议的构建器模式示例

Swift 中带有选择器的协议扩展

Swift中带有按钮的UITableViewCell [重复]

React 中带有输入的异步状态