OC单例模式详解

一、单例模式的实现

1ARC单例

1>提供一个全局静态变量,保存单例的实例,因为放在静态区,我们不需要关心释放问题,等待程序结束的时候,系统将实例与其他的静态去变量一同销毁

static id instance;

2>提供全局访问的方法通常以shared+类名,单例获取方法保证对象只被分配一次内存空间(实例化一次)

+ (instancetype)shared类名{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

instance  = [[self alloc] init];

});

return instance;

}

3>重写allocWithZone方法,保证只给单例对象分配一次内存(实例化一次)。因为对象的实例化alloc实质上是要调用+allocWithZone:方法,只要重写该方法,基本就能实现单例

4、在实现单例的时候通常使用GCD的dispatch_once()函数来保证单例的线程安全

5、具体实现(其实什么都没有干,只是给allocWithZone加上线程安全)

+ (instancetype)allocWithZone:(struct _NSZone *)zone{

static dispatch_once_t onceToken;

dispatch_once(&onceToken,^{

if(!instance){

instance = [super allocWithZone:zone];

}

});

return instance;

}

6、因为copy同样能产生新的对象copyWithZone:

- (id)copyWithZone:(NSZone *)zone{

return instance;

}

2MRC单例

处理实现ARC部分的单例需要做的事情,还得实现MRC下的内存管理相关的方法

- (instancetype)retain {

    return instance;

}


- (instancetype)autorelease {

    return instance;

}


//为了防止用NSLog输出retainCount可以实现retainCount方法给一个够大的数,吓死哪些细化打印retainCount的人

就像NSString一样,打印NSString的retainCount如果是64bit系统,会返回一个2^64的数ULONG_MAX,我们可以模仿

- (NSUInteger)retainCount {

   return ULONG_MAX;

}

二、单例宏抽取

1、##在连接前后变量为一个变量

2、宏换行用\

3、__has_feature(objc_arc)判断是否是ARC环境


#define singletonInterface(className)          + (instancetype)shared##className;


#if __has_feature(objc_arc)

// 以下是ARC版本

#define singletonImplementation(className) \

+ (instancetype)allocWithZone:(struct _NSZone *)zone { \

    static dispatch_once_t onceToken; \

    dispatch_once(&onceToken, ^{ \

        if (instance == nil) { \

            instance = [super allocWithZone:zone]; \

        } \

    }); \

    return instance; \

} \

+ (instancetype)shared##className { \

    static dispatch_once_t onceToken; \

    dispatch_once(&onceToken, ^{ \

        instance = [[self alloc] init]; \

    }); \

    return instance; \

} \

- (id)copyWithZone:(NSZone *)zone { \

    return instance; \

}

#else

// 以下是MRC版本

#define singletonImplementation(className) \

+ (instancetype)allocWithZone:(struct _NSZone *)zone { \

    static dispatch_once_t onceToken; \

    dispatch_once(&onceToken, ^{ \

        if (instance == nil) { \

            instance = [super allocWithZone:zone]; \

        } \

    }); \

    return instance; \

} \

+ (instancetype)shared##className { \

    static dispatch_once_t onceToken; \

        dispatch_once(&onceToken, ^{ \

        instance = [[self alloc] init]; \

    }); \

    return instance; \

} \

- (id)copyWithZone:(NSZone *)zone { \

    return instance; \

} \

- (oneway void)release {} \

- (instancetype)retain {return instance;} \

- (instancetype)autorelease {return instance;} \

- (NSUInteger)retainCount {return ULONG_MAX;}

#endif


// 提示末尾一行不要有 \


三、小结

单例实现(只要重写了allocWithZone方法,其余方法的重写,都直接返回我们定义好的保存单例对象的静态变量)

1、提供一个保存单例实现的静态变量

2、重写allocWithZone方法

3、提供工厂方法shared+类名

4、如果是MRC的重写retain,release,autorelease,retainCount方法

5、重写copyWithZone

6、单例宏的使用

只要传入想要实现的单例对象的类型,即可实现一个单例

7、常见的单例

UIApplication

NSNotificationCenter

NSFileManager

NSUserDefaults


四、一句话单例

自己实现单例的时候,只要提供一个静态变量用来保存单例对象;重写所有能产生对象的方法(MRC比ARC多重写内存管理的方法release,autorelease,retain,retainCount);重写必要方法的时候,只要allocWithZone,和retainCount(返回ULONG_MAX),其余方法一律返回静态变量;提供工厂方法shared+类名创建对象


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值