使用扩展实现单例

小于 1 分钟阅读

注意!转载请注明出处作者,谢谢

感谢 yerl 的指导。

1. OC篇

基于万物继承于 NSObject 的思想,我们可以写一个 NSObject 的扩展来为它增加单例方法,就不需要我们每次要写单例的时候都撸一遍,不继承 NSObject 的类那就自己撸自己吧。

使用运行时获取调用单例方法的类,然后取出此类的实例,如果实例为空则实例化。

#import "NSObject+MKInstance.h"
#import <objc/runtime.h>

@implementation NSObject (MKInstance)

+(instancetype)instance {
    const void *INSTACE = &INSTACE;
    __block id _instance_ = objc_getAssociatedObject(self, INSTACE);
    if(!_instance_) {
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            if(!_instance_) {
                _instance_ = [self new];
                objc_setAssociatedObject(self, INSTACE, _instance_, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
            }
            dispatch_semaphore_signal(sema);
        });
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    }
    return _instance_;
}

@end

2. Swift篇

swift 跟 OC 不一样,它是面向协议编程,也是就是说它没有所谓的超级父类,所有的值类型、引用类型并没有统一的父类或者协议。所以要想 OC 一样写一个统一的单例方法是不行的,那么通过继承包含单例方法的类或者协议行吗?协议不能声明 static let 的属性,out!swift 的动态类型 AnyClass 不能动态实例化,也不行,只能在具体类里添加单例方法了:

class MKInstance  {
    static let sharedInstance = MKInstance()
    private init() {}
}

断点运行看看:

截图

static let 是使用 dispatch_once 函数执行的,所以 sharedInstance 是一个单例对象。

更新: