【问题标题】:How can I initialize a class property that depends on an initializer argument as well as `self`?如何初始化依赖于初始化器参数以及“self”的类属性?
【发布时间】: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 没有额外的访问成本。
  • 另外,ConsumerSupplier 不应存储彼此的强链接。检查他们是否这样做。否则你会有内存泄漏。如果是这样,您应该将其中一个更改为weak,并将weak 更改为Optional
  • 如果没有可变性,就不可能创建这样的链(Consumer 对象包含一个供应商,它引用了消费者)。必须首先创建一个对象(与 nil 对应),然后必须创建另一个对象(引用第一个),然后可以将第一个对象设置为引用第二个。
  • 使用属性包装器,您可以在 property wrapper 中捕获这种延迟初始化模式
  • @user28434 Implicitly Unwrapped Optionals 仍然是 Optionals,根据 swift.org/blog/iuo 中的 Implicit Unwrapping is Part of a Declaration 进行一些额外的检查;我似乎找不到任何可以比较性能的搜索结果。

标签: swift


【解决方案1】:

另一种方法是将consumerSupplier 中声明为weak optional 以避免保留循环(Consumer 持有对Supplier 的强引用,反之亦然)

class Consumer
{
    let supplier: Supplier

    init(observer: Observer)
    {
        self.supplier = Supplier(observer: observer)
        supplier.consumer = self
    }
}

class Observer {}

class Supplier
{
    let observer : Observer
    weak var consumer : Consumer?

    init(observer: Observer, consumer: Consumer? = nil) {
        self.observer = observer
        self.consumer = consumer
    }
}

这是 Swift:没有尾随分号。

【讨论】:

    猜你喜欢
    • 2021-10-09
    • 1970-01-01
    • 2017-11-29
    • 2015-01-17
    • 2012-07-25
    • 1970-01-01
    相关资源
    最近更新 更多