Swift项目中如何将[ViewController.answer]类型值传递至另一视图控制器?
嘿,我刚好对苹果《App Development with Swift》里的这个个性测验项目很熟悉!你遇到的类型传递错误是页面间传值时的典型问题,咱们一步步来排查解决:
1. 先核对接收端的属性类型是否完全匹配
首先要确认你在ResultsViewController中定义的接收答案的属性,和QuestionViewController里要传递的答案集合类型完全一致。比如教材里的项目中,答案是自定义的Answer结构体,那你的Results控制器里必须这样声明:
// 必须和传递的集合类型严格匹配,不能是[String]或其他类型 var responses: [Answer]!
如果这里的类型写错了,比如把[Answer]写成了[String],就会直接触发类型不兼容的报错。
2. 确保在正确的时机完成传值
你需要在QuestionViewController的prepare(for:sender:)方法里完成数据传递,这是Storyboard segue传值的标准方式。注意要先判断segue的标识符,再正确强转目标控制器:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // 替换成你在Storyboard里设置的segue标识符,别拼写错! guard segue.identifier == "ShowResults", let resultsVC = segue.destination as? ResultsViewController else { return } // 把你存储答案的数组赋值给目标控制器的属性 resultsVC.responses = userAnswers }
这里容易踩的坑:要么是segue标识符拼写错误,导致代码没进入赋值逻辑;要么是没有把segue.destination强转成ResultsViewController,导致无法访问到接收属性。
3. 检查发送端的答案集合类型
再确认QuestionViewController里存储答案的数组类型,必须和接收端的属性类型完全一致。比如教材里的项目中,应该是这样声明的:
// 存储用户选择的答案,类型为[Answer] var userAnswers = [Answer]()
如果不小心把这个数组声明成了其他类型(比如[Int]或者[String]),传递的时候自然会出现类型不匹配的错误。
4. 避免在接收端过早使用未赋值的属性
如果你在ResultsViewController的viewDidLoad里直接使用这个答案集合,可能会因为传值还没完成导致可选值为nil的问题。可以把处理逻辑放到viewWillAppear里,或者给属性添加didSet观察者:
var responses: [Answer]! { didSet { // 在这里处理答案计算逻辑,比如生成个性结果 calculatePersonalityResult() } }
内容的提问来源于stack exchange,提问作者Mahaffey

