我来自Objective C背景,我通常用于在给定类的init方法中声明我的属性(类的全局变量),例如:
-(instancetype) init {
self = [super init];
if(self){
self.viewModel = [[MyViewModel alloc] init:self];
}
return self;
}
当self.viewModel是一个属性时,我通常将视图控制器作为参数传递给视图模型以进行回调。我现在正试图在swift中做同样的事情。
我有一个普通的自定义视图控制器类,使用以下init方法:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nil, bundle: nil)
self.viewModel = SearchViewModel(callback: self)
}
现在有了上面的代码,xcode抱怨
self.viewModel尚未初始化
但是当我尝试初始化viewModel时,即:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
self.viewModel = SearchViewModel(callback: self)
super.init(nibName: nil, bundle: nil)
}
然后我得到
在super.init调用之前自我使用
我如何在Swift中解决这个问题?
答案 0 :(得分:2)
首先关闭:_.map(arr1, obj => _.find(arr2, o => o.id === obj.id) || obj);
初始化程序希望在调用超级初始化程序之前正确设置Swift
的所有属性/具有值。
第二关:你不能在self
- 调用之前使用self
,否则你在超级构造函数中设置的属性还没有设置,意味着接收< / em>未完成的super.init
- 实例无法确定self
的状态。
解决方案:设置self
类型的viewModel
并使用第一个代码替换。
说明:通过使SearchViewModel!
隐式展开的可选项,它在开头隐式包含viewModel
,因此您现在可以调用nil
并设置实际值之后到super.init
。
答案 1 :(得分:1)
您编写的代码永远不会在Swift中编译。原因是,在self
完全初始化之前,您无法将SearchViewModel
传递给self
(即,其所有非零属性都具有值),但您无法完全初始化self
而不给它一个视图模型。
这很可能是一个参考周期,你会泄漏内存。
要解决此问题,请将callback
SearchViewModel
属性设置为可选,或者将视图控制器的viewModel属性设置为可选。这允许您在完全初始化对象之前完全初始化,而不提供引用,并允许您使引用变弱,从而阻止引用循环。
所以,如果您认为weak var viewModel: SearchViewModel?
在您取消引用它时永远不会weak var viewModel: SearchViewModel!
并且愿意承担风险,那么您可以写SearchViewModel
或nil
崩溃。