从不同的 VC 访问时,带有完成处理程序的 API 调用函数崩溃

Posted

技术标签:

【中文标题】从不同的 VC 访问时,带有完成处理程序的 API 调用函数崩溃【英文标题】:API call function with completion handler crashes when accessed from different VC 【发布时间】:2017-11-28 11:26:33 【问题描述】:

有人可以修复我的函数代码吗,因为我创建了一个 API 调用函数,它将获取我类中特定对象的 imageURL 并在第二个视图控制器中显示结果。我创建了自定义完成处理程序,以便仅在完成 ​​imageURL 的下载时执行来自第二个 VC 的代码。

但是,当我在第二个视图控制器中测试此功能以打印它已到达的数据时,我在打印语句行上遇到了崩溃。

这是我在模型类文件中的 API 调用函数的代码:

func parseImageData(finished: () -> Void) 

    let urlPath = _exerciseURL
    let url = URL(string: urlPath!)

    let task = URLSession.shared.dataTask(with: url!)  (data, response, error) in

        if error != nil 
            print("Error while parsing JSON")
        
        else 

            do 
                if let data = data,
                    let fetchedImageData = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String:Any],
                    let images = fetchedImageData["results"] as? [[String: Any]] 


                    for eachImage in images 
                        let imageUrl = eachImage["image"] as! String
                        self._imageUrl = URL(string: imageUrl)
                    

                    print(self._imageUrl)


                
            
            catch 
                print("Error while parsing data.")
            
        

    
    task.resume()
    finished()

在第二个视图控制器中,我只是在测试是否可以访问代码块:

override func viewDidLoad() 
    super.viewDidLoad()

    exercise.parseImageData() 
        print("Arrived Here?") // I am getting crash on this line moving to debug navigator.

    


【问题讨论】:

请设置完成处理程序完成()(之前或之后)打印(self._imageUrl)并让我知道它是否工作? 崩溃说什么? 您是否在 parseImageData 完成处理程序中执行任何 UI 更新? 显然在 print 语句之前移动 finished() 迫使我将函数参数更改为 @escaping 但它可以工作,现在它可以访问第二个 VC 中的代码块。我仍然不明白怎么做,因为它似乎表明在任务中间完成,但谢谢你的帮助。 在您的代码中,finished() 在代码执行后调用,而不是在响应到来后调用。这就是为什么将它移动到封闭内的原因。大括号中URLSession.shared.dataTask(with: url!) 之后的部分在您收到响应/错误后执行 【参考方案1】:

如果崩溃说明了force unwrapping nil,那可能是因为let task = URLSession.shared.dataTask(with: url!) 正在展开url,这是nil 此处的可选变量。

但是无论如何,您的完成处理程序在错误的位置被调用,请尝试将您的 finished() 回调放入 do 语句中。因为finished在你调用exercise.parseImageData()的那一刻就被执行了

if error != nil 
   print("Error while parsing JSON")

else 

    do 
        if let data = data,
            let fetchedImageData = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as? [String:Any],
            let images = fetchedImageData["results"] as? [[String: Any]] 


            for eachImage in images 
                let imageUrl = eachImage["image"] as! String
                self._imageUrl = URL(string: imageUrl)
            

            print(self._imageUrl)

            finished()
        
    
    catch 
        print("Error while parsing data.")
    

【讨论】:

我移动了它并开始工作,但我不知道为什么在视图控制器中更新图像需要大约 10 秒。 您需要将图像视图更新分派到主队列。

以上是关于从不同的 VC 访问时,带有完成处理程序的 API 调用函数崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Swift:带有完成处理程序的多线程

VC串口通信问题

Swift:在解雇的完成处理程序中呈现 VC

从委托的源 ViewController 调用异步闭包

从 Java Script (TVML) 调用带有完成处理程序的 Swift 函数

自托管 web api 并从单元测试项目中访问它