为了账号安全,请及时绑定邮箱和手机立即绑定

在SWIFT中使用调度单例模型

在SWIFT中使用调度单例模型

森林海 2019-06-03 16:17:22
在SWIFT中使用调度单例模型我正试图为SWIFT中的使用找出一个合适的单例模型。到目前为止,我已经能够得到一个非线程安全模型,其作用是:class var sharedInstance:TPScopeManager {     get {         struct Static {             static var instance : TPScopeManager? = nil         }         if !Static.instance {             Static.instance = TPScopeManager()         }         return Static.instance!     }}将单例实例封装在静态结构中应该允许单个实例在没有复杂命名方案的情况下不会与单例实例发生冲突,并且应该使事情变得相当私密。但是很明显,这个模型并不是线程安全的,所以我尝试在整个过程中添加调度_ONE:class var sharedInstance:TPScopeManager {     get {         struct Static {             static var instance : TPScopeManager? = nil             static var token : dispatch_once_t = 0         }         dispatch_once(Static.token) { Static.instance = TPScopeManager() }         return Static.instance!     }}但是,我在dispatch_once行:无法将表达式的类型“void”转换为“()”类型我尝试过几个不同的语法变体,但它们似乎都有相同的结果:dispatch_once(Static.token, { Static.instance = TPScopeManager() })什么是正确的用法?dispatch_once用斯威夫特?我最初认为问题是由于()在错误消息中,但是我越看它,我就越认为这可能是一个获得dispatch_once_t正确定义。
查看完整描述

3 回答

?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

TL;DR:使用类常数如果您正在使用SWIFT1.2或更高版本,并且嵌套结构如果需要支持早期版本,请使用此方法。

根据我使用SWIFT的经验,有三种方法可以实现Singleton模式,它们支持延迟初始化和线程安全。

类常数

class Singleton  {
   static let sharedInstance = Singleton()}

此方法支持延迟初始化,因为Swift延迟初始化类常量(和变量),并且通过let..

SWIFT 1.2中引入了类常数。如果需要支持SWIFT的早期版本,请使用下面的嵌套结构方法或全局常量。

嵌套结构

class Singleton {
    class var sharedInstance: Singleton {
        struct Static {
            static let instance: Singleton = Singleton()
        }
        return Static.instance    }}

这里我们使用嵌套结构的静态常数作为类常量。这是SWIFT1.1及更早版本中缺少静态类常量的一种解决方法,并且仍然可以解决函数中缺少静态常量和变量的问题。

派遣一次

传统的目标-C方法移植到SWIFT。我相当肯定,与嵌套的struct方法相比没有什么优势,但我还是把它放在这里,因为我发现语法上的差异很有趣。

class Singleton {
    class var sharedInstance: Singleton {
        struct Static {
            static var onceToken: dispatch_once_t = 0
            static var instance: Singleton? = nil
        }
        dispatch_once(&Static.onceToken) {
            Static.instance = Singleton()
        }
        return Static.instance!
    }}


查看完整回答
反对 回复 2019-06-03
?
白衣非少年

TA贡献1155条经验 获得超0个赞

由于Apple现在已经澄清静态struct变量被初始化为延迟并被包装在调度_ONE中(请参阅文章末尾的注释),我认为我的最后解决方案将是:

class WithSingleton {
    class var sharedInstance :WithSingleton {
        struct Singleton {
            static let instance = WithSingleton()
        }

        return Singleton.instance    }}

这利用了静态结构元素的自动延迟、线程安全初始化,向使用者安全地隐藏了实际实现,使所有内容保持紧凑的可读性,并消除了一个可见的全局变量。

苹果已经澄清,延迟初始化程序是线程安全的,因此不需要dispatch_once或类似的保护

全局变量的延迟初始化器(也适用于结构和枚举的静态成员)将在第一次访问全局变量时运行,并以调度_ONE的形式启动,以确保初始化是原子的。这使得在代码中使用调度一次的方法很酷:只需使用初始化器声明一个全局变量,并将其标记为私有变量即可。


查看完整回答
反对 回复 2019-06-03
  • 3 回答
  • 0 关注
  • 636 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信