Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 何时使用swift初始化viewController全局变量_Ios_Swift - Fatal编程技术网

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

Ios 何时使用swift初始化viewController全局变量,ios,swift,Ios,Swift,我来自Objective C背景,通常习惯于在给定类的init方法中声明我的属性(类的全局变量),例如: -(instancetype) init { self = [super init]; if(self){ self.viewModel = [[MyViewModel alloc] init:self]; } return self; } 当self.viewModel是一个属性,并且我通常将视图控制器作为参数传递给视图模型以进行回调时。我目前正试图在

我来自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中进行分类?

您编写的代码永远不会在Swift中编译。原因是在
self
完全初始化之前(即,它的所有非nil属性都有一个值),您无法将
self
传递到
SearchViewModel
),但如果不给它一个视图模型,您就无法完全初始化
self

这很可能是一个引用循环,您将泄漏内存

要解决此问题,请将
SearchViewModel
callback
属性设置为可选,或将视图控制器的viewModel属性设置为可选。这允许您在对象完全初始化之前完全初始化,而不提供引用,并允许您使引用变弱,从而防止引用循环


所以你要写
弱var视图模型:SearchViewModel?
,或者
弱var视图模型:SearchViewModel
,如果您相信在解除引用时,
SearchViewModel
将永远不会是
nil
,并且愿意冒崩溃的风险。

首先:
Swift
初始化程序希望在调用超级初始化程序之前正确设置
self
的所有属性

第二个问题:在调用
super.init
-之前,不能使用
self
,因为如果不这样,您将在超级构造函数中设置的属性尚未设置,这意味着接收未完成的
self
-实例的任何人都无法确定
self
的状态

解决方案:制作
SearchViewModel类型的
viewModel
并使用第一个代码选项


说明:通过使
viewModel
成为隐式展开的可选项,它在开始时隐式包含
nil
,因此,您现在可以调用
super.init
,然后将实际值设置为
viewModel

尝试使用
viewDidLoad
函数。为此,我必须在init方法中初始化viewModel,然后在viewDidLoad方法中编写setter方法来设置对viewModel的回调。这真的是唯一的解决方案吗?您可以/应该将
viewModel
声明为
SearchViewModel类型并使用第一个代码替代项。这将使代码正常工作。为什么会这样?