iOS开发程序员iOS Developer

iOS开发之单例

2018-05-04  本文已影响144人  hmj1993

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

单例模式

arc环境下实现单例模式

#import <Foundation/Foundation.h>
//重写copy的相关方法时必须引入copy的相关文件
@interface danli : NSObject<NSCopying,NSMutableCopying>

//类方法
//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的开发环境,如下图所示


屏幕快照 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,也就是我们自己设置的单例名称

#define singerH(name) +(instancetype)share##name;
#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开发中单例的相关使用方法

上一篇下一篇

猜你喜欢

热点阅读