iOS开发之单例

由于iOS开发中经常会用到单例,所以就做个简单的总结。
单例模式

  • 作用:
    可以保证在程序运行过程中,一个类只有一个实例,而且该实例易于供外界访问,从而方便的控制了实例个数,并节约系统资源
  • 使用场合:
    在整个应用程序中,共享一份资源(这份资源只需要创建初始化一次)
arc环境下实现单例模式
#import //重写copy的相关方法时必须引入copy的相关文件 @interface danli : NSObject//类方法 //1.方便访问 //2.标明身份 //3.命名规范 share/default + 类名 +(instancetype)shareDanli; @end

#import "danli.h"@implementation danli//0.提供全局变量 static danli *_instance; //1.alloc +(instancetype)allocWithZone:(struct _NSZone *)zone { //method 1 //加互斥锁解决多线程访问安全问题 @synchronized(self){if (_instance==nil) { _instance=[super allocWithZone:zone]; } }//method 2 //本身就是线程安全的,不需要担心多线程安全问题 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance=[super allocWithZone:zone]; }); return _instance; } //2.提供类方法 +(instancetype)shareDanli{ return [[self alloc]init]; } //3.严谨,因为有的时候不止是alloc或new方法创建 -(id)copyWithZone:(NSZone *)zone{ return _instance; } -(id)mutableCopyWithZone:(NSZone *)zone{ return _instance; } @end

以上就是在arc的环境下构建单例的方法,mrc的环境下构建单例的方法差不多,就是多重写几个方法
mrc环境下实现单例模式
首先,设置一下mrc的开发环境,如下图所示

iOS开发之单例
文章图片
屏幕快照 2018-05-04 下午2.56.09.png
其次,因为在mrc环境下需要在创建实例后进行release操作,但这显然和单例的目标相违背,所以为了不进行销毁,我们可以重写以下方法,
-(oneway void)release{ } -(instancetype)retain{ return _instance; } -(NSUInteger)retainCount{ return MAXFLOAT; }

这样就已经实现了我们的目标
但是考虑到如果经常切换mrc和arc的环境,我们就需要经常修改相关方法,所以为了解决这个问题,我们可以使用条件编译来动态的根据开发环境来进行mrc和arc的不同考虑,也就是将mrc的相关代码放在条件编译的else语句中,这样也就不需要经常修改代码了
//条件编译 #if __has_feature(objc_arc) //arc #else //mrc -(oneway void)release{ } -(instancetype)retain{ return _instance; } -(NSUInteger)retainCount{ return MAXFLOAT; } #endif

以上已经完成了单例的操作,但是在一个大的项目中,我们肯定不会只有一个单例,而单例的代码其实也都差不多,如果每次都进行复制,在代码的复用问题上又做的不是很好,所以我们可以考虑将单例的代码写成宏,这样就可以方便使用了,其中,这里使用了带参数的宏,参数即为name,也就是我们自己设置的单例名称
  • 定义.h文件的宏
#define singerH(name) +(instancetype)share##name;

  • 定义.m文件的宏,其中也是使用条件编译区分arc和mrc的开发环境
#if __has_feature(objc_arc) //arc #define singerM(name) static id *_instance; \ +(instancetype)allocWithZone:(struct _NSZone *)zone\ {\ @synchronized(self){\ if (_instance==nil) {\ _instance=[super allocWithZone:zone]; \ }\ }\ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{\ _instance=[super allocWithZone:zone]; \ }); \ return _instance; \ }\ +(instancetype)share##name{\ return [[self alloc]init]; \ }\ -(id)copyWithZone:(NSZone *)zone{\ return _instance; \ }\ -(id)mutableCopyWithZone:(NSZone *)zone{\ return _instance; \ } #else //mrc #define singerM(name) static id *_instance; \ +(instancetype)allocWithZone:(struct _NSZone *)zone\ {\ @synchronized(self){\ if (_instance==nil) {\ _instance=[super allocWithZone:zone]; \ }\ }\ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{\ _instance=[super allocWithZone:zone]; \ }); \ return _instance; \ }\ +(instancetype)share##name{\ return [[self alloc]init]; \ }\ -(id)copyWithZone:(NSZone *)zone{\ return _instance; \ }\ -(id)mutableCopyWithZone:(NSZone *)zone{\ return _instance; \ }\ -(oneway void)release{\ }\ -(instancetype)retain{\ return _instance; \ }\ -(NSUInteger)retainCount{\ return MAXFLOAT; \ }\ #endif

在使用时,只要在自己创建的单例文件中调用相关的参数宏就可以了
【iOS开发之单例】以上,就是iOS开发中单例的相关使用方法

    推荐阅读