当前位置: 首页 > 知识库问答 >
问题:

在Swift中使用dispatch_once单例模型

田翰林
2023-03-14

我正在尝试为Swift中的使用制定一个合适的单例模型。到目前为止,我已经能够使一个非线程安全模型工作为:

class var sharedInstance: TPScopeManager {
    get {
        struct Static {
            static var instance: TPScopeManager? = nil
        }

        if !Static.instance {
            Static.instance = TPScopeManager()
        }

        return Static.instance!
    }
}

将单个实例包装在静态结构中应该允许一个不与没有复杂命名模式的单个实例冲突的单个实例,并且应该使事情相当私有。但是很明显,这个模型不是线程安全的。所以我尝试将dispatch_once添加到整个过程中:

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() })

共有1个答案

杜河
2023-03-14

如果您正在使用Swift1.2或更高版本,请使用类常量方法;如果您需要支持早期版本,请使用嵌套结构方法。

根据我使用Swift的经验,有三种方法可以实现支持惰性初始化和线程安全的单例模式。

class Singleton  {
   static let sharedInstance = Singleton()
}

这种方法支持惰性初始化,因为Swift会惰性初始化类常量(和变量),并且通过let的定义是线程安全的。这是现在官方推荐的实例化单例的方法。

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

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

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

传统的Objective-C方法移植到Swift。我相当肯定,与嵌套结构方法相比,它没有任何优势,但我还是把它放在这里,因为我发现语法上的差异很有趣。

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!
    }
}

有关单元测试,请参阅此GitHub项目。

 类似资料:
  • 问题内容: 我正在尝试制定一个合适的单例模型以在Swift中使用。到目前为止,我已经能够获得一个非线程安全模型,其工作方式如下: 在静态结构中包装单例实例应该允许一个不与单例实例冲突的单实例,而无需复杂的命名方案,并且应该使事情变得相当私有。但是,显然,此模型不是线程安全的。所以我试图添加到整个事情: 但是我在网上遇到了一个编译器错误: 无法将表达式的类型“无效”转换为类型“()” 我尝试了几种不

  • 问题内容: 好的,所以我在Xcode 8中找到了新的SwiftyDispatchAPI。我在使用中很有趣,并且我一直在Xcode中的模块周围浏览以找到所有新的API。 但是我也要确保单例创建和一次性设置之类的操作不会被执行多次(即使在多线程环境中也是如此)…并且在新的Dispatch模块中找不到任何地方吗? 问题答案: 从Swift 1.x开始,Swift一直 在幕后使用全局变量和静态属性执行线程

  • 问题内容: 语言版本3进行更改后,Swift中的新语法是什么?旧版本如下。 这些是对libdispatch所做的更改。 问题答案: 从文档: 派遣 自由功能dispatch_once不再提供斯威夫特。在Swift中,您可以使用延迟初始化的全局变量或静态属性,并获得与提供的dispatch_once相同的线程安全性和一次调用保证。例:

  • 本文向大家介绍深入理解Swift中单例模式的替换及Swift 3.0单例模式的实现,包括了深入理解Swift中单例模式的替换及Swift 3.0单例模式的实现的使用技巧和注意事项,需要的朋友参考一下 前言 除了 MVC、MVVM 之外,单例模式可以说是 iOS 开发中另一常见的设计模式。无论是 UIKit 或是一些流行的三方库,我们都能看到单例的身影。而我们开发者本身也会潜意识地将这些类库中的代码

  • 如何使用单例模式 可以看下这个图: 这是一个日志类,有一个属性 (是一个单例对象) 和两个方法 (sharedInstance() 和 init())。 第一次调用 sharedInstance() 的时候,instance 属性还没有初始化。所以我们要创建一个新实例并且返回。 下一次你再调用 sharedInstance() 的时候,instance 已经初始化完成,直接返回即可。这个逻辑确保了

  • 本文向大家介绍通过示例分析Swift单例模式,包括了通过示例分析Swift单例模式的使用技巧和注意事项,需要的朋友参考一下 三种Swift实现单例模式的方法:全局变量,内部变量,dispatch_once方式 1. 全局变量 2. 内部变量 3. dispatch_once方式 以上所述就是本文的全部内容了,希望大家能够喜欢。