在单例结构

时间:2017-12-20 12:26:41

标签: swift singleton

我在swift中有一个关于单身人士的简单问题,经过大量研究后我没有找到明确的答案。所以问题是 - 我有StructA

struct StructA {
    static let shared = StructA()

    private init() {}

    public func someFuncA() {
       //self.somefuncB()
       //or
       //StructA.shared.someFuncB()
    }

    private func someFuncB() {

    }
}

我从其他类调用someFuncA,例如StructA.shared.someFuncA()

  1. 您能解释一下self.somefuncB()StructA.shared.someFuncB()的区别(见上面的代码)吗? 在我看来没有区别,但如果我必须在回调中调用self.somefuncB()时有这样的代码怎么办?

  2. 我必须使用[weak self]吗?

    public func someFuncA() {
        someFuncWithCallback() { [weak self] in
            self?.somefuncB()
        }
    }
    

    或者我可以写

    public func someFuncA() {
        someFuncWithCallback() {
            StructA.shared.someFuncB()
        }
    }
    

    我用" Leaks"检查了这段代码。 (Xcode乐器)它说没有泄漏,因为我知道close / block拥有其中使用的对象,所以有人可以解释一下这里发生了什么吗?感谢。

1 个答案:

答案 0 :(得分:2)

有几点想法:

  1. struct单身是一个矛盾。单例是一个应该只有一个实例的对象。但struct是一种价值类型,并且有"复制"记忆语义。考虑:

    var a = StructA.shared
    ...
    

    a是所谓的单身人士的副本,而不是对它的引用。为避免此问题,单例应为class,即引用类型。

  2. 我同意Paulw11,self是一种更简单,更常见的方法。不过,我还建议,通过引用self,您可以更好地编写代码(a)不依赖于作为单例的类; (b)在未来的某个日期开启该课程的分类可能性。

  3. 鉴于我会建议self模式,因此我建议避免明显潜在的强引用周期(例如,在需要时使用weakunowned引用。没有必要故意创造出强大的参考周期,因为它恰好是一个单身人士。为什么要编写您知道的代码,如果您重新考虑使用单例模式的决定,尤其是当您知道首先避免使用强引用时是多么容易?

  4. 仅供参考,我看到您报告的行为相同,如果static参与理论上的强参考周期,则不会将其识别出来。但是,如果将static属性设置为nil(假设它是可变的和可选的),则会出现强引用。

    这一观察结果并未改变我的建议,即避免在任何其他情况下你所知道的强烈参考周期。我只是在证实你的经验观察。

  5. 关于上面的第2点到第4点(我考虑了一些潜在的最终重构单例模式到其他模式),我应该说这不是纯粹的学术观察。拥有一些单例类型并且随后随着项目变得更复杂或采用更多单元测试,重新审视该决策并开始使用依赖注入或其他模式,这种情况并不少见。如果您还必须编辑所有单个函数,那将是一种耻辱。如果编写的代码不依赖于对象的单例性质,那么最终会得到更强大的代码库,同时减少不必要的内部依赖性。