链接到静态 TableView 中的控件的插座未初始化
Outlets linked to controls in a Static TableView are not initialized
我正在尝试设置主详细信息导航。
我使用故事板,master 是动态的 table,details 是静态的 table。
我有一个 nameLabel 设置作为控制器中的出口,但是当我尝试在 viewDidLoad 中访问它时,它仍然设置为 nil。
我没有使用 prepareForSegue,而是使用了 didSelectRowAtIndexPath,它像这样推送详细视图:(因为我使用的是 TableViewBindingHelper,请参阅 https://github.com/ColinEberhardt/ReactiveTwitterSearch/tree/master/ReactiveTwitterSearch/Util)
func showLessonView(lessonVM: LessonViewModel) {
let lessonViewController = LessonViewController(WithViewModel: lessonVM)
self.navigationController?.pushViewController(lessonViewController, animated: true)
}
课程视图控制器:
import Foundation
import ReactiveCocoa
class LessonViewController: UITableViewController {
@IBOutlet var lessonNameLabel: UILabel!
private var viewModel: LessonViewModel
init(WithViewModel viewModel: LessonViewModel){
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
bindData()
}
func bindData() {
// null here!
if (lessonNameLabel != nil) {
lessonNameLabel.rac_text <~ viewModel.name
}
}
}
我该如何解决这个问题?
我看到的其他示例代码在 segue 中执行导航,最终调用 init(coder aDecoder: NSCoder) 构造函数并且所有出口都已初始化。
因为您使用 WithViewModel
初始化程序初始化视图控制器,所以它对情节提要一无所知,因此插座没有连接。要按照情节提要中指定的方式连接出口,您需要使用 segue,或者使用情节提要的 instantiateViewControllerWithIdentifier(identifier:)
方法来创建视图控制器。无论哪种方式,您都不能(轻松地)将 ViewModel 作为参数传递给初始化,因此您需要公开 viewModel var(删除 private
)并在 showLessonView
方法中单独设置它。要使用 instantiateViewControllerWithIdentifier(identifier:)
,请在情节提要中为您的 Lesson View Controller
提供一个标识符(比如 "LessonViewController")。然后修改你的showLessonView
如下:
func showLessonView(lessonVM: LessonViewModel) {
let lessonViewController = self.storyboard!.instantiateViewControllerWithIdentifier(identifier:"LessonViewController") as! LessonViewController
lessonViewController.viewModel = lessonVM
self.navigationController?.pushViewController(lessonViewController, animated: true)
}
当视图控制器从情节提要中实例化时,会使用 init(coder:)
初始化程序,因此要么删除该方法的覆盖,要么修改它以调用超级实现:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
我正在尝试设置主详细信息导航。
我使用故事板,master 是动态的 table,details 是静态的 table。
我没有使用 prepareForSegue,而是使用了 didSelectRowAtIndexPath,它像这样推送详细视图:(因为我使用的是 TableViewBindingHelper,请参阅 https://github.com/ColinEberhardt/ReactiveTwitterSearch/tree/master/ReactiveTwitterSearch/Util)
func showLessonView(lessonVM: LessonViewModel) {
let lessonViewController = LessonViewController(WithViewModel: lessonVM)
self.navigationController?.pushViewController(lessonViewController, animated: true)
}
课程视图控制器:
import Foundation
import ReactiveCocoa
class LessonViewController: UITableViewController {
@IBOutlet var lessonNameLabel: UILabel!
private var viewModel: LessonViewModel
init(WithViewModel viewModel: LessonViewModel){
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
bindData()
}
func bindData() {
// null here!
if (lessonNameLabel != nil) {
lessonNameLabel.rac_text <~ viewModel.name
}
}
}
我该如何解决这个问题?
我看到的其他示例代码在 segue 中执行导航,最终调用 init(coder aDecoder: NSCoder) 构造函数并且所有出口都已初始化。
因为您使用 WithViewModel
初始化程序初始化视图控制器,所以它对情节提要一无所知,因此插座没有连接。要按照情节提要中指定的方式连接出口,您需要使用 segue,或者使用情节提要的 instantiateViewControllerWithIdentifier(identifier:)
方法来创建视图控制器。无论哪种方式,您都不能(轻松地)将 ViewModel 作为参数传递给初始化,因此您需要公开 viewModel var(删除 private
)并在 showLessonView
方法中单独设置它。要使用 instantiateViewControllerWithIdentifier(identifier:)
,请在情节提要中为您的 Lesson View Controller
提供一个标识符(比如 "LessonViewController")。然后修改你的showLessonView
如下:
func showLessonView(lessonVM: LessonViewModel) {
let lessonViewController = self.storyboard!.instantiateViewControllerWithIdentifier(identifier:"LessonViewController") as! LessonViewController
lessonViewController.viewModel = lessonVM
self.navigationController?.pushViewController(lessonViewController, animated: true)
}
当视图控制器从情节提要中实例化时,会使用 init(coder:)
初始化程序,因此要么删除该方法的覆盖,要么修改它以调用超级实现:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}