Swift单例与静态属性/方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift单例与静态属性/方法相关的知识,希望对你有一定的参考价值。

根据this blog postcurrently highest voted answerthis Stack Overflow question,后者引用Apple's documentation,在现代Swift中创建单身人士的最佳方式是:

class Singleton  {
   static let sharedInstance = Singleton()
}

虽然没有提到,但也可能需要private init()

对我来说,更简单的替代方法是将所有属性和方法转换为static,并删除sharedInstance属性。

例如,假设我按照上面的建议编写了一个带有属性和方法的类,如下所示:

class Singleton {
  static let sharedInstance = Singleton("whatever")

  var myProperty: String

  func myMethod() {
    // ...
  }

  private init(_ myProperty) {
    self.myProperty = myProperty
  }
}

如果用户需要访问有问题的属性,他们会写Singleton.sharedInstance.myProperty,如果他们需要调用方法,他们会写Singleton.sharedInstance.myMethod()

我建议改写课程如下:

class Singleton {
  static var myProperty: String = "whatever"

  static func myMethod() {
    // ...
  }
}

因此:更少的样板代码,以及访问属性(只需Singleton.myProperty)和方法(Singleton.myMethod())时输入的字符更少。

一个缺点是,从类内部访问属性和方法需要完全拼写(Singleton.myPropertySingleton.myMethod()),而之前的解决方案只需要myPropertymyMethod()

因此,对于用户来说(对sharedInstance部分掉线)更容易一点,对于类编写者来说有点困难(需要在所有访问之前添加Singleton.)。当面对有利于用户或类作者的设计选择时,更好的选择是支持用户,这似乎是合理的。

似乎没有其他人提倡我提出的制作单身人士的方法,所以我觉得必须有一些问题。有人会如此善良地指出它是什么吗?

答案

对我来说,更简单的替代方法是将所有属性和方法转换为静态,并删除sharedInstance属性。

这些不做同样的事情。推荐的方法实际上根本不是单身人士。这只是一个众所周知的例子。 Singleton模式的概念是必须只有一个实例。共享实例模式的音乐会是可以有多个实例,但有一个您可能想要的实例,并且您希望能够轻松访问它。

共享实例的优点是它们并不神奇。他们只是一个例子。这意味着他们可以作为价值观交付。它们可以替换为可能配置不同的其他实例。它们更容易测试(因为它们可以传递给函数)。

真正的单例是一种非常严格的模式,只有在绝对没有其他实例存在的情况下才能使用,通常是因为它们与某些外部独特资源交互,如果存在倍数会产生冲突(这种情况非常罕见)。即使在这种情况下,在Swift中,通常只需将init设为私有以防止创建其他实例。

如果你环顾Cocoa,你会发现共享实例对于其他框架中的Singletons来说非常常见,而且这个实例非常强大。例如,有一个着名的NotificationCenter叫做default,它可能是你用过的唯一一个。但是创建一个独立的私有NotificationCenter是完全有效的(我实际上已经在生产代码中完成了这个)。

事实上,UIDevice.current是您访问设备的方式,而不是静态方法,这使得新API可以处理多个设备的可能性(它也有助于单元测试)。在最早的ios版本中,唯一的UIScreen.main,它可能有意义使其成为单身人士。但是因为Apple没有,当4.3中添加了镜像时,谈论第二个屏幕(UIScreen.mirrored)很简单。你通常应该很慢地假设只能有一个东西。

以上是关于Swift单例与静态属性/方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 3 将单例与 Alamofire 一起使用?

PHP:单例与静态类 [重复]

类和对象的方法与属性---懒加载与私有事件---单例与私有化构造函数

并发编程:单例与多线程

@Component单例与并发

如何在类扩展中添加静态(存储)属性以制作单例? (迅速)