在 Swift 中实现单例方法
2015-09-07 16:53
323 查看
我们通常在进行开发的时候,会用到一个叫做 单例模式 的东西。相信大家也都对这种模式非常熟悉了。而且单例的使用在平时的开发中也非常频繁。 比如我们常用到的
在 Swift 中我们如何实现单例模式呢?如果你曾经对 Objective-C 比较熟悉的话,你可能首先会想到这样写:
从 Objective-C 的思路上来看,这样好像没有什么问题。但在 Swift 中,那么问题就来了。因为 Swift 中是不支持静态成员变量的,所以这行代码
那么就是说,在 Swift 中我们不能通过静态成员变量的方式实现单例方法了。那么还有什么其他的办法呢。我们还可以将实例变量的定义放到类的外面,比如这样:
这种方式是可以实现单例的,但会有一个问题。就是我们可以在任何文件中访问到
那么,还有什么方法呢?
Swift 中还有一种属性叫做 Computed 属性,而这种属性是可以定义成为静态类型的。 比如这样:
但是这个属性又有一个问题,就是它的值每次都需要经过计算生成的,也就是上面代码中大括号内的部分。所以它不能单独作为实例变量存放的地方,它只能够作为访问的入口。我们还需要一个地方来存储实例变量。
而我们又知道,Swift 的类定义中,又不能存在静态成员变量,而且把这个实例变量定义在类的外面又会失去封装性。那还有什么办法呢? 真急人。
还好,经过我们的仔细探索,发现了这么一个宝藏。那就是
这个
这样,我们的单例就基本完成了,把 struct 的定义放到了属性方法的里面,这样从类的外面就不能访问到它,保证了类的封装性。
基本很完美了,那么接下来,我们还要考虑最后一个问题,就是 线程安全,其实做起来也很简单,就是添加以下
Objective-C 开发的同学对这个方法并不陌生。
那么最后,我们完成后的单例模式定义如下:
NSUserDefaults.standardUserDefaults()。
在 Swift 中我们如何实现单例模式呢?如果你曾经对 Objective-C 比较熟悉的话,你可能首先会想到这样写:
class DBManager { class var instance: DBManager? class func sharedInstance() -> DBManager { if !instance { instance = DBManager() } return instance! } }
从 Objective-C 的思路上来看,这样好像没有什么问题。但在 Swift 中,那么问题就来了。因为 Swift 中是不支持静态成员变量的,所以这行代码
class var instance: DBManager?会产生编译错误。
那么就是说,在 Swift 中我们不能通过静态成员变量的方式实现单例方法了。那么还有什么其他的办法呢。我们还可以将实例变量的定义放到类的外面,比如这样:
var instance: DBManager? class DBManager { class func sharedInstance() -> DBManager { if !instance { instance = DBManager() } return instance! } }
这种方式是可以实现单例的,但会有一个问题。就是我们可以在任何文件中访问到
instance这个变量,这样就很容易造成对这个实例变量的意外操作,并且这也不符合面向对象思想中的封装特性。
那么,还有什么方法呢?
Swift 中还有一种属性叫做 Computed 属性,而这种属性是可以定义成为静态类型的。 比如这样:
class DBManager { class var sharedInstance: DBManager { // return the single instance } }
但是这个属性又有一个问题,就是它的值每次都需要经过计算生成的,也就是上面代码中大括号内的部分。所以它不能单独作为实例变量存放的地方,它只能够作为访问的入口。我们还需要一个地方来存储实例变量。
而我们又知道,Swift 的类定义中,又不能存在静态成员变量,而且把这个实例变量定义在类的外面又会失去封装性。那还有什么办法呢? 真急人。
还好,经过我们的仔细探索,发现了这么一个宝藏。那就是
struct结构。虽然
class定义中是不允许使用静态成员变量的,但是
struct是可以的。比如我们可以这样写:
struct Private { static var instance: DBManager? }
这个
struct结构是可以顺利编译通过的。我们接下来要做的就是将它和 DBManager 类结合起来:
class DBManager { class var sharedInstance: DBManager { struct Private { static var instance: DBManager? } if !Private.instance { Private.instance = DBManager() } return Private.instance! } }
这样,我们的单例就基本完成了,把 struct 的定义放到了属性方法的里面,这样从类的外面就不能访问到它,保证了类的封装性。
基本很完美了,那么接下来,我们还要考虑最后一个问题,就是 线程安全,其实做起来也很简单,就是添加以下
dispatch_once的调用。相信熟悉
Objective-C 开发的同学对这个方法并不陌生。
那么最后,我们完成后的单例模式定义如下:
class DBManager { class var sharedInstance: DBManager { struct Private { static var instance: DBManager? static var token: dispatch_once_t = 0 } dispatch_once(&Private.token) { Private.instance = DBManager() } return Private.instance! } }
相关文章推荐
- Apple Swift学习教程
- Swift中实现点击、双击、捏、旋转、拖动、划动、长按手势的类和方法介绍
- Swift中定义二维数组的方法及遍历方法示例
- 简单分析Swift语言的一些基本特征
- Swift与C语言指针结合使用实例
- Swift心得笔记之控制流
- 用Swift构建一个简单的iOS邮件应用的方法
- 苹果公司推出的新编程语言Swift简介和入门教程
- Swift中的指针操作和使用详细介绍
- Swift中使用正则表达式的一些方法
- Swift心得笔记之运算符
- Swift中使用可选类型完美解决占位问题
- Swift学习笔记之构造器重载
- Swift中的Access Control权限控制介绍
- Swift类型创建之自定义一个类型详解
- Swift教程之控制流详解
- Swift中初始化方法的顺序介绍
- Swift里的值类型与引用类型区别和使用
- Swift调用Objective-C编写的API实例