在 Swift 中使用 dispatch_once 单例模型 [英] Using a dispatch_once singleton model in Swift

查看:52
本文介绍了在 Swift 中使用 dispatch_once 单例模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to work out an appropriate singleton model for usage in Swift. So far, I've been able to get a non-thread safe model working as:

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

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

        return Static.instance!
    }
}

将单例实例包装在静态结构中应该允许在没有复杂命名方案的情况下不会与单例实例发生冲突的单个实例,并且它应该使事情变得相当私密.显然,这个模型不是线程安全的.所以我尝试将 dispatch_once 添加到整个事情中:

Wrapping the singleton instance in the Static struct should allow a single instance that doesn't collide with singleton instances without complex naming schemings, and it should make things fairly private. Obviously though, this model isn't thread-safe. So I tried to add dispatch_once to the whole thing:

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 行上收到编译器错误:

But I get a compiler error on the dispatch_once line:

无法将表达式的类型 'Void' 转换为类型 '()'

Cannot convert the expression's type 'Void' to type '()'

我尝试了几种不同的语法变体,但它们似乎都有相同的结果:

I've tried several different variants of the syntax, but they all seem to have the same results:

dispatch_once(Static.token, { Static.instance = TPScopeManager() })

dispatch_once 使用 Swift 的正确用法是什么?由于错误消息中的 () ,我最初认为问题出在块上,但是我看的越多,我就越认为这可能是获取 dispatch_once_t 的问题 正确定义.

What is the proper usage of dispatch_once using Swift? I initially thought the problem was with the block due to the () in the error message, but the more I look at it, the more I think it may be a matter of getting the dispatch_once_t correctly defined.

推荐答案

tl;dr:如果您使用的是 Swift 1.2 或更高版本且 嵌套的,请使用 类常量 方法struct 方法,如果您需要支持早期版本.

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

From my experience with Swift there are three approaches to implement the Singleton pattern that support lazy initialization and thread safety.

class Singleton  {
   static let sharedInstance = Singleton()
}

这种方法支持延迟初始化,因为 Swift 延迟初始化类常量(和变量),并且根据 let 的定义是线程安全的.这现在是正式的推荐的方法来实例化一个单例.

This approach supports lazy initialization because Swift lazily initializes class constants (and variables), and is thread safe by the definition of let. This is now officially recommended way to instantiate a singleton.

类常量是在 Swift 1.2 中引入的.如果您需要支持早期版本的 Swift,请使用下面的嵌套结构方法或全局常量.

Class constants were introduced in Swift 1.2. If you need to support an earlier version of Swift, use the nested struct approach below or a global constant.

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

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

Here we are using the static constant of a nested struct as a class constant. This is a workaround for the lack of static class constants in Swift 1.1 and earlier, and still works as a workaround for the lack of static constants and variables in functions.

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

The traditional Objective-C approach ported to Swift. I'm fairly certain there's no advantage over the nested struct approach but I'm putting it here anyway as I find the differences in syntax interesting.

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 项目.

See this GitHub project for unit tests.

这篇关于在 Swift 中使用 dispatch_once 单例模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆