【发布时间】:2019-07-09 23:13:15
【问题描述】:
我是一名新的 Swift 开发人员。是否有合适的模式来初始化类变量,其初始化程序需要引用 self?
示例代码:
class Consumer
{
var supplier: Supplier;
init(observer: Observer)
{
// error: 'self' used before all stored properties are initialized
self.supplier = Supplier(observer: observer, consumer: self);
}
}
class Observer {}
class Supplier
{
init(observer: Observer, consumer: Consumer) {/*do init*/}
}
我可以使该属性成为显式解包的可选项,但这对我来说是错误的,因为我不想产生与可选项相关的成本(该变量将在紧密循环中访问)。这个假设是错误的吗?显式解包选项是否提供与常规 a var 相当的性能,或者它们是否仍在访问检查?
class Consumer
{
var supplier: Supplier!; // explicitly unwrapped Optional
init(observer: Observer)
{
/*
pro: problem solved
con?: accessing supplier incurs the costs of accessing an Optional?
*/
self.supplier = Supplier(observer: observer, consumer: self);
}
}
/*other classes*/
我可以有一个额外的变量来首先初始化类,然后是一个惰性变量,以便能够使用self,但是我在类中存储了一个额外的变量,初始化之后就不需要了。
class Consumer
{
var observer: Observer; // never used elsewhere after initialization
lazy var supplier: Supplier = Supplier(observer: observer, consumer: self);
init(observer: Observer)
{
/*
pro: problem solved
con: small memory overhead
*/
self.observer = observer;
}
}
/*other classes*/
注意:我不是在寻找关于引用依赖周期的建议,只是针对所述问题。
【问题讨论】:
-
隐式展开的 Optional 没有额外的访问成本。
-
另外,
Consumer或Supplier不应存储彼此的强链接。检查他们是否这样做。否则你会有内存泄漏。如果是这样,您应该将其中一个更改为weak,并将weak更改为Optional。 -
如果没有可变性,就不可能创建这样的链(Consumer 对象包含一个供应商,它引用了消费者)。必须首先创建一个对象(与
nil对应),然后必须创建另一个对象(引用第一个),然后可以将第一个对象设置为引用第二个。 -
使用属性包装器,您可以在 property wrapper 中捕获这种延迟初始化模式
-
@user28434 Implicitly Unwrapped Optionals 仍然是 Optionals,根据 swift.org/blog/iuo 中的
Implicit Unwrapping is Part of a Declaration进行一些额外的检查;我似乎找不到任何可以比较性能的搜索结果。
标签: swift