【问题标题】:Delegate pattern use but ı get Unexpectedly found nil while implicitly unwrapping an Optional value Error Message使用委托模式,但在隐式展开可选值错误消息时意外发现 nil
【发布时间】:2021-12-27 16:43:56
【问题描述】:

我昨天克隆了这个项目,它包括两个 ViewControllers 和 SelectionScreen 使用委托设计模式将数据发送到 BaseScreen。这是我的第一个代码与控制器分离

import UIKit

class BaseScreen: UIViewController {

    @IBOutlet weak var mainImageView: UIImageView!
    @IBOutlet weak var chooseButton: UIButton!
    @IBOutlet weak var nameLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        chooseButton.layer.cornerRadius = chooseButton.frame.size.height/2
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

    @IBAction func chooseButtonTapped(_ sender: UIButton) {
        let selectionVC = storyboard?.instantiateViewController(withIdentifier: "SelectionScreen") as! SelectionScreen
        selectionVC.selectionDelegate=self
        present(selectionVC, animated: true, completion: nil)
    }
}

extension BaseScreen: SideSelectionDelegate {
    
    func didTapChoice(image: UIImage, name: String, color: UIColor) {
        mainImageView.image = image
        nameLabel.text = name
        view.backgroundColor = color
    }
    
}

import UIKit

protocol SideSelectionDelegate {
    func didTapChoice(image: UIImage, name: String, color: UIColor)
}

class SelectionScreen: UIViewController {
    
    var selectionDelegate: SideSelectionDelegate!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func imperialButtonTapped(_ sender: UIButton) {
       
        selectionDelegate.didTapChoice(image: UIImage(named: "vader")!, name: "Darth Vader", color: .red)
        dismiss(animated: true, completion: nil)
    }

    @IBAction func rebelButtonTapped(_ sender: UIButton) {
      
        selectionDelegate.didTapChoice(image: UIImage(named: "luke")!, name: "Luke Skywalker", color: .cyan)
        dismiss(animated: true, completion: nil)
    }
}

这很完美,但是当我改成这个时

import UIKit

class BaseScreen: UIViewController {

    @IBOutlet weak var mainImageView: UIImageView!
    @IBOutlet weak var chooseButton: UIButton!
    @IBOutlet weak var nameLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        chooseButton.layer.cornerRadius = chooseButton.frame.size.height/2
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

    @IBAction func chooseButtonTapped(_ sender: UIButton) {
        let selectionVC = storyboard?.instantiateViewController(withIdentifier: "SelectionScreen") as! SelectionScreen
     **//   selectionVC.selectionDelegate=self**
        present(selectionVC, animated: true, completion: nil)
    }
}


extension BaseScreen: SideSelectionDelegate {
    
    func didTapChoice(image: UIImage, name: String, color: UIColor) {
        mainImageView.image = image
        nameLabel.text = name
        view.backgroundColor = color
    }
    
}

import UIKit

protocol SideSelectionDelegate {
    func didTapChoice(image: UIImage, name: String, color: UIColor)
}

class SelectionScreen: UIViewController {
    
    var selectionDelegate: SideSelectionDelegate!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func imperialButtonTapped(_ sender: UIButton) {
        **let vc=storyboard?.instantiateViewController(withIdentifier: "BaseScreen") as! BaseScreen
        self.selectionDelegate=vc**
        selectionDelegate.didTapChoice(image: UIImage(named: "vader")!, name: "Darth Vader", color: .red)
        dismiss(animated: true, completion: nil)
    }

    @IBAction func rebelButtonTapped(_ sender: UIButton) {
        **let vc=storyboard?.instantiateViewController(withIdentifier: "BaseScreen") as! BaseScreen
        self.selectionDelegate=vc**
        selectionDelegate.didTapChoice(image: UIImage(named: "luke")!, name: "Luke Skywalker", color: .cyan)
        dismiss(animated: true, completion: nil)
    }
}

我收到此错误

任何人都可以帮助我,我知道它太长了,但我认为解决方案太容易了 谢谢你的一切

【问题讨论】:

  • 您有问题的代码正在创建 BaseScreen 视图控制器的 NEW 实例,将 self.selectionDelegate 设置为该 NEW 实例,然后(如果您没有收到错误消息)您的代码会丢弃该新实例。那么,第一个问题:为什么你想做出这样的改变?
  • 我想以不同的方法解决这种数据传输问题。我认为无论是在基本屏幕还是共享屏幕中的实例,委托都会完美地工作,但我不工作。谢谢建议。但我想有其他问题。实际上委托工作即使我做了这个糟糕的例子。我可以完美地打印数据但是当我尝试更改标签文本时它崩溃了为什么? @DonMag
  • thx @matt 这对我来说是一个巨大的建议。我有同样的问题,我在上面问过
  • @Sait47 - 这真的不清楚......你是说你的BaseScreen 可能正在显示,而你呈现SelectionScreen - 此时点击“反叛按钮”应该会关闭选择屏幕和更新基本屏幕...并且您想显示SelectionScreen,并且点击“反叛按钮”应该将BaseScreen 显示为共享屏幕?

标签: ios swift delegates


【解决方案1】:

@IBOutlet 元素在视图加载之前不可用。

如果添加这一行,就不会出现“unexpectedly found nil...”错误:

@IBAction func rebelButtonTapped(_ sender: UIButton) {

    let vc=storyboard?.instantiateViewController(withIdentifier: "BaseScreen") as! BaseScreen

    // add this line to force the controller to load its view NOW       
    vc.loadViewIfNeeded()
    
    self.selectionDelegate=vc
    selectionDelegate.didTapChoice(image: UIImage(named: "luke")!, name: "Luke Skywalker", color: .cyan)
    
}

但是,一旦该代码执行,BaseScreen 的新实例将不复存在。所以它不会完成任何事情。

不过,此时您可以致电 present(vc, animated: true, completion: nil),例如。

【讨论】:

  • 感谢您@DonMag,现在我的问题已经解决了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多