【问题标题】:Initialize lazy instance variable with value that depends on other instance variables使用依赖于其他实例变量的值初始化惰性实例变量
【发布时间】:2016-10-05 07:11:45
【问题描述】:

以下初始化当前在调用getEventCalendar 的行中产生此错误:

不能在属性中使用实例成员“getEventCalendar” 初始化器;属性初始化程序在 'self' 可用之前运行。

是否有任何合适的方法来初始化lazy 实例变量,其值取决于self 的其他对象类型instance variables(不仅仅是self alone)?我有例如尝试将 getEventCalendar 从方法转换为函数,但这也无济于事。

class AbstractEventCalendarClient {

  let eventStore: EKEventStore
  let entityType: EKEntityType

  lazy var eventCalendar = getEventCalendar()

  init(eventStore: EKEventStore, entityType: EKEntityType) {
    self.eventStore = eventStore
    self.entityType = entityType
  }

  func getEventCalendar() -> EKCalendar? {
    // ...
  }
}

【问题讨论】:

标签: swift swift3 lazy-evaluation


【解决方案1】:

您可以使用只执行一次的闭包,它捕获self 的属性并在执行时使用它们(= 首次使用lazy 属性)。例如

class Foo {
    var foo: Int
    var bar: Int
    lazy var lazyFoobarSum: Int = { return self.foo + self.bar }()

    init(foo: Int, bar: Int) { 
        self.foo = foo 
        self.bar = bar
    }
}

let foo = Foo(foo: 2, bar: 3)
foo.foo = 7
print(foo.lazyFoobarSum) // 10

W.r.t.自己尝试:同样,您可以在这个只执行一次的闭包中使用self 的帮助(实例)函数。

class Foo {
    var foo: Int
    var bar: Int
    lazy var lazyFoobarSum: Int = { return self.getFooBarSum() }()

    init(foo: Int, bar: Int) { 
        self.foo = foo 
        self.bar = bar
    }

    func getFooBarSum() -> Int { return foo + bar }
}

let foo = Foo(foo: 2, bar: 3)
foo.foo = 7
print(foo.lazyFoobarSum) // 10

【讨论】:

  • 是的,聪明。我现在使用这个逐字逐句:lazy var eventCalendar: EKCalendar? = { return self.getEventCalendar() }().
  • @Drux:lazy var eventCalendar: EKCalendar? = self.getEventCalendar() 也应该可以工作,这是在@Hamish 的(现已删除)答案中提出的。
  • 确切地说是 8 秒 :)
  • @Drux 我相信 Hamish 的回答在 w.r.t.您的错误消息(而我的详细 asnwer 有点偏离轨道,更侧重于一般的惰性属性实例化):显式类型注释,除了在实例方法前加上 self.,是两个缺失的项目。跨度>
  • @Drux 很抱歉这么过早地删除了我的答案——我刚刚去听讲座,看到了 Martin 的链接问答,一眼看去,我认为这将是一个合适的欺骗目标。尽管再次查看它,虽然 非常 相似,但此问题的解决方案不同之处在于您需要显式引用 self 才能使用实例成员。出于这个原因,我现在取消了我的答案:)
【解决方案2】:

这是一个令人困惑的错误消息(您可能很想file a bug report on)。问题只是lazy 属性的一个怪癖——它们目前需要显式使用self 才能访问实例成员,并且在这样做时需要显式类型注释(之前已在this Q&A 中指出) .

因此你需要说:

lazy var eventCalendar: EKCalendar? = self.getEventCalendar()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2011-03-18
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多