繁体   English   中英

崩溃:使用SDWebImage更新UIImageView时

[英]Crash: While updating UIImageView using SDWebImage

我要实现的是,当用户单击任何CollectionViewCell时,将显示一个新视图以进行缩放滚动 基本上,我有两个不同的类,分别名为MyCollectionViewController和MyScrollViewController。 我的集合视图控制器中有以下代码部分:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let VC = storyboard.instantiateViewController(withIdentifier: "myScrollVC") as? MyScrollViewController
    self.navigationController?.pushViewController(VC!, animated: true)
    VC?.setImageToScrollView(image_URL: (self.jsonData?.HD_WALLPAPER![indexPath.row].wallpaper_image)!)
}

我的滚动视图控制器中有以下代码部分:

import UIKit
import SDWebImage
class MyScrollViewController: UIViewController, UIScrollViewDelegate {
    @IBOutlet weak var myImageView: UIImageView!
    @IBOutlet weak var myScrollView: UIScrollView!
    override func viewDidLoad(){
        super.viewDidLoad()
        self.myScrollView.minimumZoomScale = 1.0
        self.myScrollView.maximumZoomScale = 6.0
    }
    public func setImageToScrollView(image_URL: String){
        DispatchQueue.main.async {
            self.myImageView!.sd_setImage(with: URL(string: image_URL), completed: {
                (image, error, cacheType, url) in
                //Completion Block ... Do Nothing
            })
        }
    }
    override func didReceiveMemoryWarning(){
        super.didReceiveMemoryWarning()
    }
    func viewForZooming(in scrollView: UIScrollView) -> UIView?{
        return self.myImageView
    }
}

我正在使用SDWebImage ...一个开放源代码库来管理图像缓存。

问题 :有时成功加载图像而没有任何错误,但是大多数情况下,我的应用在执行SDWebImage框架的sd_setImage api时崩溃 ,并显示以下错误…… 在此处输入图片说明

致命错误:展开一个可选值时意外发现nil

查询

  1. 首先,我调用了pushViewController,然后调用了自定义函数。 从集合视图单元格调用函数是否正确?
  2. 为什么在展开Optional值时显示意外发现nil ..虽然我得到了无错误的图像URL。

回到您的问题:

首先,我调用了pushViewController,然后调用了自定义函数。 从集合视图单元格调用函数是否正确?

答案是,在viewDidLoad之前,不要调用引用插座的函数。 这些插座是隐式解包的可选组件,但直到viewDidLoad才保证存在。 因此,您有比赛条件。 有时可以。

对其进行更改,以便您传递URL,但不要调用该函数:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let VC = storyboard.instantiateViewController(withIdentifier: "myScrollVC") as? MyScrollViewController
    self.navigationController?.pushViewController(VC!, animated: true)
    VC.imgURL =  self.jsonData?.HD_WALLPAPER![indexPath.row].wallpaper_image)!
}

其中imgURL是MyScrollViewContainer上的实例变量。 然后从viewDidLoad调用函数,并传入imgURL。

override func viewDidLoad(){
    super.viewDidLoad()
    self.myScrollView.minimumZoomScale = 1.0
    self.myScrollView.maximumZoomScale = 6.0
    setImageToScrollView(image_URL: imgURL)
}

这将改变您的调用时间-确保在调用函数时插座确实存在。

===剩下的就是我以前的答案(仍然很重要,但是没有解决您的问题)===

您无需将SetImage调用包装在Dispatch.async中。 您的函数应为一行:

public func setImageToScrollView(image_URL: String){
   self.myImageView.sd_setImage(with: URL(string: image_URL))
}

那应该使您的问题消失。 SetImage进行自己的调度,并且仅在出口仍然存在时才更新UI。

其他评论者指出了为什么您的代码有时会崩溃(当异步块完成时self.myImageView可能为nil)以及如何防范(如果让其绑定或警惕以检查UIImageView出口是否仍然存在)。 这些通常是相关的技术-但是SetImage会为您解决所有这些问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM