当前位置: > > > Swift - 单例模式的实现

Swift - 单例模式的实现

过去 Swift 要实现单例,无非是这三种方式:全局变量,内部变量和 dispatch_once 方式。但都略显繁琐。
后来从 1.2 版本起,Swift 中添加了如 static letstatic var 这样的类变量的支持,这样单例的实现又简化了许多。

下面提供两种比较好的单例写法。(要注意:不管哪种写法都要注意将 init() 方法私有化。因为在 Swift 中,所有对象的构造器默认都是 public,需要重写 init 让其成为私有的,防止其他对象使用这个类的默认的'()'初始化方法来创建对象。这里感谢网友nowIsFuture的提醒。)

方法1:
class AppManager {
    private static let _sharedInstance = AppManager()
    
    class func getSharedInstance() -> AppManager {
        return _sharedInstance
    }
    
    private init() {} // 私有化init方法
}

//使用方式
AppManager.getSharedInstance()

方法2:
class AppManager {
    static let sharedInstance = AppManager()
    
    private init() {} // 私有化init方法
}

//使用方式
AppManager.sharedInstance

附一:为什么需要保证INIT的私有化? 

因为只有 init() 是私有的,才能防止其他对象通过默认构造函数直接创建这个类对象,确保你的单例是真正的独一无二。 
因为在 Swift 中,所有对象的构造器默认都是 public,所以需要重写你的 init 让其成为私有的。这样就保证像如下的代码编译报错,不能通过。
var a1 = AppManager() //确保编译不通过
var a2 = AppManager() //确保编译不通过

附二:如何将单例对象置为nil?

有时我们可能需要将单例对象设为 nil,或重新创建一个新的实例。我们可以使用如下代码实现:
class AppManager {
    private static var _sharedInstance: AppManager?
    
    class func getSharedInstance() -> AppManager {
        guard let instance = _sharedInstance else {
            _sharedInstance = AppManager()
            return _sharedInstance!
        }
        return instance
    }
    
    private init() {} // 私有化init方法
    
    //销毁单例对象
    class func destroy() {
        _sharedInstance = nil
    }
}

//使用方式
AppManager.getSharedInstance()
AppManager.destroy()
评论4
  • 4楼
    2017-05-16 16:26

    能不能把对象直接置空啊?因为我单例里面的属性太多了,一个个去写也是比较麻烦的,如果能把单例对象置空的话就方便多了

    站长回复

    非要把对象置空也是可以实现,我在文章末尾补充了相关代码,你可以再看下。

  • 3楼
    2017-05-16 16:16

    接2楼,那我这样的话是要在这个重置方法里面把每一个属性都要写出来,然后让它们等于""么?还是说有比较简单的写法?

    站长回复

    对的,重置方法里属性要一个个重新赋值。当然你也可考虑使用反射和kvc来自动遍历赋值,参考:Swift - 反射(Reflection)的介绍与使用样例(附KVC介绍)。不过个人觉得还是直接手动赋值更好。

  • 2楼
    2017-05-16 14:25

    你好我想问一下,我创建了一个单例,单例类里面定义了很多属性用来记录值,但是在我的项目里面需要在退出登录的时候需要把所有的属性赋值给清空,我想了俩办法,一个是把单例对象nil,另一个是把单例里面的所有的属性赋值清空,但是查了好多资料,没有关于swift 单例清空的。。求详解一下

    站长回复

    根据你的描述,直接在单例类里添加个重置方法好了,这个方法将所有属性给清空。退出登录时调用下这个方法即可。

  • 1楼
    2015-08-24 18:32
    这块显卡有点冷

    想请问一下,private static let sharedInstance = AppManager() 为什么需要 加private。这样岂不是在别的文件中不能反问到了吗?还有一个就是为什么需要把 init()这个构造器私有化?

    站长回复

    1,private static let sharedInstance = AppManager()前的private是我写错了,多谢提醒。 2,init私有化是为了保证单例类实例的唯一性。我在文章中现也详细解释了。总之,构造函数私有化的不一定是单例类。但单例类构造函数一定是私有化的。