何时使用swift初始化viewController全局变量

时间:2016-06-18 16:24:02

标签: ios swift

我来自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中解决这个问题?

2 个答案:

答案 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!并且愿意承担风险,那么您可以写SearchViewModelnil崩溃。