参考文章:https://github.com/hpique/SwiftSingleton
swift中常用的单例有三种写法:
1、最简单的一种:定义static常量,只执行一次
Approach A: Class constant
class SingletonA {
static let sharedInstance = SingletonA()
init() {
println("AAA");
}
2、使用结构体
3、仿照OC的写法
static let sharedInstance = SingletonA()
init() {
println("AAA");
}
}
2、使用结构体
Approach B: Nested struct
class SingletonB {
class var sharedInstance: SingletonB {
struct Static {
static let instance: SingletonB = SingletonB()
}
return Static.instance
}
struct Static {
static let instance: SingletonB = SingletonB()
}
return Static.instance
}
}
说明:1、创建一个类变量的计算属性。类变量类似Objective-C中的类方法,也就是说在任何时候你访问
sharedInstance
属性时,都不需要对SingletonB进行实例化
2、在类变量中内嵌一个结构体,名为Static
3、Static中包含一个名为
instance
的静态常量属性。用static
申明属性意味着该属性只能存在一份。这里要注意的是Swift中的静态属性都会延迟加载,也就是说只有instance
被使用时,才会初始化它。还要注意的一点是,一旦instance
被初始化了,那么它就是一个常量属性,不会有第二次初始化的机会了。这就是Singleton模式的精髓所在
3、仿照OC的写法
Approach C: dispatch_once
The traditional Objective-C approach ported to Swift.
class SingletonC {
class var sharedInstance: SingletonC {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: SingletonC? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = SingletonC()
}
return Static.instance!
}
class var sharedInstance: SingletonC {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: SingletonC? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = SingletonC()
}
return Static.instance!
}
}
遇到的问题:在扩展里定义单例
class AAA: NSObject {}
extension AAA {
staticlet sharedInstance = AAA()
}
运行报错:a declaration cannot be both 'final' and 'dynamic'
在stackoverflow网站找到相同错误: http://stackoverflow.com/questions/29814706/a-declaration-cannot-be-both-final-and-dynamic-error-in-swift-1-2
查找到的原因:This issue arises because Swift is trying to generate a dynamic accessor for the static property for Obj-C compatibility, since the class inherits from NSObject.
If your project is in Swift only, rather than using a var accessor you can avoid the issue via the @nonobjc attribute in Swift 2.0
问题产生是因为由于当前类是继承于NSObject的,swift为了swift和Obj-C的兼容为静态变量生成一个动态访问器,如果你的工程是只支持swift的,你可以使用@nonobjc属性避免这个问题
@nonobjc属性用来选择性的禁止实例的导出