崩溃:使用SDWebImage更新UIImageView

问题描述 投票:0回答:1

我想要实现的是,当用户点击任何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时崩溃,并出现以下错误...... enter image description here

致命错误:在解开Optional值时意外发现nil

查询:

  1. 首先我调用了pushViewController,然后调用了自定义函数。是从集合视图单元调用函数的正确方法吗?
  2. 为什么它展开意外发现nil同时展开一个可选值..虽然我得到无错误的图像网址。
ios swift uiimageview sdwebimage
1个回答
0
投票

回到你的问题:

首先我调用了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)
}

这将改变您的通话时间 - 确保在调用该功能时插座实际存在。

===其余的是我之前的答案(仍然相关,但没有解决你的问题)===

您不需要在Dispatch.async中包装SetImage调用。你的功能应该是一行:

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

这应该会让你的问题消失。 SetImage自己进行调度,只有在插座仍然存在时才更新UI。

其他评论者指出为什么你的代码有时会崩溃(当异步块完成时self.myImageView可能是nil)以及如何防止(如果让绑定或保护检查UIImageView插槽仍然存在)。这些都是相关的技术 - 但SetImage会为您处理所有这些。

© www.soinside.com 2019 - 2024. All rights reserved.