如何修复“快速协议/代理设置UIImages-致命错误:意外发现nil,而隐式展开一个Optional值”?

时间:2019-07-04 05:19:03

标签: swift uiimageview delegates uiimage protocols

我让用户在登录时选择背景图像。基于用户对图像选择的选择,我想显示另一个视图控制器以及用户选择的图像。我按照youtube上的一些示例进行操作,但出现“致命错误:在隐式展开Optional值时意外发现nil”,并且未设置图片。

protocol SelectionImageDelegate {

    func setBackgroundImage(selectedImage: UIImage)
}


class SelectBackgroundViewController: UIViewController {

    // MARK: IBOutlets
    @IBOutlet weak var snowBackgroundImage: UIImageView!
    @IBOutlet weak var desertBackgroundImage: UIImageView!
    @IBOutlet weak var pathwayBackgroundImage: UIImageView!
    @IBOutlet weak var beachBackgroundImage: UIImageView!

    // MARK: Properties
    var imageSelectionDelegate: SelectionImageDelegate!


    // MARK: Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        self.imageSelectionDelegate = FootprintViewController()
        setButtonCorners()
    }

    override func viewWillAppear(_ animated: Bool) {

        snowBackgroundImage.center.x  -= view.bounds.width
        desertBackgroundImage.center.x -= view.bounds.width
        pathwayBackgroundImage.center.x -= view.bounds.width
        beachBackgroundImage.center.x -= view.bounds.width
    }


    @IBAction func didTappedSnowBackground(_ sender: Any) {
        print("tapped snow")
        imageSelectionDelegate.setBackgroundImage(selectedImage: UIImage(named: "Snow_Background")!)
        print("set image")
        let vc = (self.storyboard?.instantiateViewController(withIdentifier: "FootprintVC"))!
        self.presentViewController(vc)
    }


    @IBAction func didTappedDesertBackground(_ sender: Any) {
        imageSelectionDelegate.setBackgroundImage(selectedImage: UIImage(named: "Desert_Background")!)
        let vc = (self.storyboard?.instantiateViewController(withIdentifier: "FootprintVC"))!
        self.presentViewController(vc)
    }


    @IBAction func didTappedPathwayBackground(_ sender: Any) {
        imageSelectionDelegate.setBackgroundImage(selectedImage: UIImage(named: "Pathway_Background")!)
        let vc = (self.storyboard?.instantiateViewController(withIdentifier: "FootprintVC"))!
        self.presentViewController(vc)
    }


    @IBAction func didTappedBeachBackground(_ sender: Any) {
        imageSelectionDelegate.setBackgroundImage(selectedImage: UIImage(named: "Beach_Background")!)
        let vc = (self.storyboard?.instantiateViewController(withIdentifier: "FootprintVC"))!
        self.presentViewController(vc)
    }

}


class FootprintViewController: UIViewController {


    // MARK: IBOutlets
    @IBOutlet weak var backgroundImageView: UIImageView!
    @IBOutlet weak var emptyFootprintImageView: UIImageView!

    // MARK: Life Cycles
    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

extension FootprintViewController: SelectionImageDelegate {

    func setBackgroundImage(selectedImage: UIImage) {
        backgroundImageView.image = selectedImage
    }
}

class FootprintViewController: UIViewController {


    // MARK: IBOutlets
    @IBOutlet weak var backgroundImageView: UIImageView!
    @IBOutlet weak var emptyFootprintImageView: UIImageView!

    // MARK: Life Cycles
    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

extension FootprintViewController: SelectionImageDelegate {

    func setBackgroundImage(selectedImage: UIImage) {
        backgroundImageView.image = selectedImage
    }
}

2 个答案:

答案 0 :(得分:0)

请尝试像这样在SelectBackgroundViewController中设置最佳的imageSelectionDelegate;

var imageSelectionDelegate: SelectionImageDelegate?

答案 1 :(得分:0)

“隐式解包”意味着您正在尝试访问“隐式解包的可选”值,该值不保存值,而是nil

在您的情况下,您要处理两个可选项:

  • 可能未设置委托人imageSelectionDelegate
  • UIImage(named: "Snow_Background")可能返回nil

访问委托-如果nil将导致Unexpectedly found nil while implicitly unwrapping an Optional value错误,而访问映像-如果nil-将导致Unexpectedly found nil while unwrapping an Optional value

因此,由于您观察到第一个错误,因此委托为nil,这似乎很奇怪,因为您在viewDidLoad中进行了设置。

要进行更多调查,可以向操作处理程序中添加更多跟踪信息,以检查会发生什么情况:

@IBAction func didTappedSnowBackground(_ sender: Any) {
    print("tapped snow")

    guard imageSelectionDelegate != nil else {
        print ("delegate is not set")
        return
    }

    guard let bgImage = UIImage(named: "Snow_Background") else {
        print ("Snow_Background image does not exist")
        return
    }

    imageSelectionDelegate.setBackgroundImage(selectedImage: bgImage)
    print("set image")
    let vc = (self.storyboard?.instantiateViewController(withIdentifier: "FootprintVC"))!
    self.presentViewController(vc)
}

然后检查输出。