swift - 在单例结构中使用 self

标签 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 工具)检查了这段代码,它说没有泄漏,因为我知道 closer/block 拥有其中使用的对象,所以有人可以解释一下这里发生了什么吗?谢谢。

最佳答案

几个想法:

  1. struct 单例在术语上是自相矛盾的。单例是一个应该只有一个实例的对象。但是 struct 是一个值类型并且具有“复制”内存语义。考虑:

    var a = StructA.shared
    ...
    

    a 是所谓的单例的副本,而不是对它的引用。为了避免这个问题,单例应该是一个,一个引用类型。

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

  3. 考虑到我建议使用 self 模式,因此我也建议避免明显的潜在强引用循环(例如通过使用 weakunowned 在需要的地方引用)。仅仅因为它恰好是单例就故意创建强引用循环是没有意义的。如果您曾经重新考虑使用单例模式的决定,为什么要编写您知道必须重写的代码,尤其是当您一开始就知道避免强引用是多么容易时?

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

    这一观察并没有改变我上面的建议,即避免你所知道的在任何其他情况下都是强引用循环。我只是在证实你的经验观察。

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

关于swift - 在单例结构中使用 self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47906064/

相关文章:

c++ - 我们如何将 Phoenix Singleton 放在同一个地址? C++

C++ 为什么我的单例不维护成员值

java - 如何使用 jmockit 对单例模式进行单元测试

javascript - 为什么我的单例无法工作?

java - JVM中如何识别单例对象?

ios - swift 。如何从扩展中获取泛型?

快速关闭 View 后,iOS 应用程序卡住

ios - Swift tvOS - 当用户按下 MENU 按钮时暂停 UIImage 动画

ios - 将数组传递给新的 ViewController 时出现 EXC_BAD_ACCESS

ios - Swift 中的多个选择器 View