Swift多ViewController传值遇可选值nil崩溃问题求助
嘿,刚入门Swift的时候我也踩过一模一样的坑!咱们先来搞清楚为啥会崩溃,再一步步改对~
崩溃的根本原因
你遇到的Fatal error: Unexpectedly found nil while unwrapping an Optional value,核心问题出在时机不对:
当你在didSelectItemAt里实例化VC1/VC2并直接给label.text赋值时,这个VC的view还没被加载!IBOutlet绑定的控件(比如你的label)只有在VC的viewDidLoad()方法执行前后才会被初始化,这时候label还是nil,强行给它的text赋值就会触发崩溃。
正确的实现步骤
我们需要把「数据传递」和「UI赋值」分开,用一个中间属性来存数据,等UI加载完成后再绑定:
第一步:给目标VC添加数据存储属性
打开VC1和VC2,先定义一个用来接收数据的属性,不要直接操作label:
class VC1: UIViewController { @IBOutlet weak var label: UILabel! // 定义可选属性存选中的数据,也可以根据需求设默认值 var selection: String? override func viewDidLoad() { super.viewDidLoad() // 这里view已经加载完成,label肯定不是nil了,再赋值 if let selectedContent = selection { label.text = selectedContent } } }
VC2的代码和这个完全一致,只是类名不同。
第二步:在CollectionView的选中方法里传递数据
回到你的UICollectionViewController,在didSelectItemAt里实例化VC、给selection赋值,再跳转:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { var targetVC: UIViewController if indexPath.item == 0 { // 注意:如果你的VC是在Storyboard/XIB里创建的,不要直接用VC1()! // 要通过Storyboard实例化,比如: // let storyboard = UIStoryboard(name: "Main", bundle: nil) // let vc1 = storyboard.instantiateViewController(withIdentifier: "VC1") as! VC1 let vc1 = VC1() vc1.selection = "你选中了第一个Cell" targetVC = vc1 } else { let vc2 = VC2() vc2.selection = "你选中了第二个Cell" targetVC = vc2 } navigationController?.pushViewController(targetVC, animated: true) }
关键注意点
如果你的VC1/VC2是用Storyboard创建的,一定要用instantiateViewController(withIdentifier:)方法来实例化,不能直接用VC1()——后者不会加载Storyboard里的界面,IBOutlet控件永远是nil,还是会崩溃!
总结一下
核心原则就是:永远不要在VC的view加载完成前操作IBOutlet控件,通过中间属性传递数据,等viewDidLoad()执行后再把数据绑定到UI上,就能完美避开这个nil崩溃啦~
内容的提问来源于stack exchange,提问作者frazman

