Swift 访问;“自我”;在初始化闭包时

Swift 访问;“自我”;在初始化闭包时,swift,swift3,Swift,Swift3,在Swift 3中,dispatch_once功能被删除,建议使用初始化关闭: 让myGlobal={…global在对闭包的调用中包含初始化…}() _=myGlobal//using myGlobal将仅在第一次使用初始化代码时调用该代码 我想从初始化闭包中访问“self”实例变量,如下所示: class SomeClass { var other = SomeOtherClass() let initialize: () = { // self.o

在Swift 3中,dispatch_once功能被删除,建议使用初始化关闭:

让myGlobal={…global在对闭包的调用中包含初始化…}()

_=myGlobal//using myGlobal将仅在第一次使用初始化代码时调用该代码

我想从初始化闭包中访问“self”实例变量,如下所示:

class SomeClass {
    var other = SomeOtherClass()
    
    let initialize: () = {
        // self.other - this doesn't work, complains about unresolved identifier 'self'
        // how to access self.other here?
    } ()

    func doSomething() {
        // initialize will only be called once
        initialize
    }
}

为什么“self”在闭包中不可访问?如何使其成为?

创建“SomeClass”类的实例时,它将首先创建该实例上的所有变量和常量。在这段时间内,self可能没有完全初始化,因为它可能已经完成了设置的一半。因此,在初始化步骤完成之前,self不可用

在这个例子中,他们讨论的是一个没有自我概念的全局变量,或者是一个没有自我概念的静态常量

如果需要是实例方法/变量,您可以:

a) 让它成为一个懒惰的变量

lazy var initialise : ()->Void = { 
    return {
        // can access self here
    }    
}()
它将在您第一次调用它时创建,而不是在初始化期间创建。当然,这样会丢失常量,并且必须存储闭包,这是浪费,因为您只执行了一次

b) 将代码放入init方法中:

init() {
    // if your class doesn't have a super class, you can access self.other here. 
    // If it does have a super class (like NSObject) you must first call super.init() here to complete the initialisation. 
    // This can only be done after all other variables have been set.
}

这个引用的迁移指南示例具有误导性,因为它与一个全局变量相关

类初始化时,立即调用实例
let
常量的闭包(一次)。这就是为什么它不能使用在同一级别上声明的其他变量的原因

您可以做的是惰性地初始化
initialize
(变量名不是最好的;-))。闭包也只被称为一次,但正如指南所描述的,只有在第一次使用它时才被称为闭包


使用带有实例属性的dispatch_once来确保“每个实例一次”初始化总是错误的,例如,请参见苹果工程师的回答。那么,在Swift 3中,确保实例初始化代码只运行一次并能够设置实例变量的正确方法是什么?在这种情况下,我不能使用init()的变体,因为类(NSViewController)只需要在
NSViewController
生命周期中的某一点(即
viewdide
)之后运行一次初始化代码。在你看来,@vadian提供的答案是正确的(它似乎工作正常)吗?同时进行比较。你认为苹果的迁移指南中有什么错误?它告诉您可以使用“延迟初始化全局或静态属性”,而不是一次调度_。问题中的实例属性既不是延迟初始化的全局属性,也不是静态属性为此目的使用dispatch_一次总是错误的,因此“迁移”不适用。另请参见我对问题的评论。@MartinR这一特定语法是错误的。行
\=myGlobal
表明
let myGlobal
闭包是惰性初始化的。实际上,获取变量完全不需要这一行。迁移指南是关于一个全局变量
myGlobal
,用于在每个应用程序运行时执行一次代码,并且不能在这里应用。就我所见,《迁移指南》中没有你所说的错误。@MartinR你是对的,但断章取义,这是相当误导的。我编辑了答案以便澄清。
class SomeClass {
  let other = SomeOtherClass()

  lazy var initialize : () = {
    let test = self.other
    test.doSomething()
  }()

  func doSomething() {
    // initialize will only be called once
    _ = initialize
  }
}