工作中经常使用到单例,但通常为了方便只是提供了一个类方法shareXXX(xxx类名),在share中使用dispatch_once来实现单例,该种方式在独立开发中使用问题倒不大,如果提供给第三方使用时,就会出现问题了。会造成非单例的情况,通常都是重写allocWithZone方法,在改方法中实现单例,并且实现copy协议的copyWithZone和mutableCopyWithZone方法完善单例的实现,下面为ARC模式下单例示例
@implementation ARCSingleleModel
// 使用全局变量 可以自定义方法来销毁单例模式,从而下次再次创建是能够正常创建
static ARCSingleleModel *_instance;
static dispatch_once_t onceToken;
+(instancetype)shareArcSingle{
return [[self alloc]init];
}
//alloc 底层调用还是 allocWithZone,所以重写allocWithZone方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
// copy 方法 也会创建新的对象。为了严谨也应该重写copy方法,因copy方法最终调用的也是copyWithZone因此 重写copyWithZone和mutableCopyWithZone。mutableCopyWithZone,mutableCopyWithZone需遵守NSCopying,NSMutableCopying协议才能敲出,在写出这两个方法后可删除NSCopying,NSMutableCopying协议
-(id)copyWithZone:(NSZone *)zone{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
//销毁单例
-(void)destory{
_instance = nil;
onceToken = 0;
}
@end
下例是MRC示例,mrc下和arc下单例区别只是重写了retainCount,release,retain三个方法
// 使用全局变量 可以自定义方法来销毁单例模式,从而下次再次创建是能够正常创建
static MRCSingleModel *_instance;
static dispatch_once_t onceToken;
+(instancetype)shareMRCSingleModel{
return [[self alloc]init];
}
//alloc 底层调用还是 allocWithZone,所以重写allocWithZone方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
// copy 方法 也会创建新的对象。为了严谨也应该重写copy方法,因copy方法最终调用的也是copyWithZone因此 重写copyWithZone和mutableCopyWithZone。mutableCopyWithZone,mutableCopyWithZone需遵守NSCopying,NSMutableCopying协议才能敲出,在写出这两个方法后可删除NSCopying,NSMutableCopying协议
-(id)copyWithZone:(NSZone *)zone{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
-(void)destory{
_instance = nil;
onceToken = 0;
}
#if __has_feature(objc_arc)
//满足 arc
#else
//mrc 重写retain和relase方法就可以
-(oneway void)release{
}
- (instancetype)retain{
return _instance;
}
//习惯 在mrc情况下,实现单例 通常会重写retainCount并返回最大值
-(NSUInteger)retainCount{
return MAXFLOAT;
}
#endif
@end
如果工程中要创建多个不同类型的单例,每个都重写上面的方法将会很浪费时间,使用宏定义的方式,可以解决,下面为宏定义的实例,只要在要实现的类中引用该宏,.h文件使用SingleH方法,.m文件中使用SingleM
#ifndef Single_h
#define Single_h
#define SingleH(name) +(instancetype)share##name;
#if __has_feature(objc_arc)
#define SingleM(name) static id _instance;\
static dispatch_once_t onceToken;\
+(instancetype)share##name{\
return [[self alloc]init];\
}\
+ (instancetype)allocWithZone:(struct _NSZone *)zone{\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
-(id)copyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(void)destory{\
_instance = nil;\
onceToken = 0;\
}
//满足 arc
#else
#define SingleM(name) static id _instance;\
static dispatch_once_t onceToken;\
+(instancetype)share##name{\
return [[self alloc]init];\
}\
+ (instancetype)allocWithZone:(struct _NSZone *)zone{\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
return _instance;\
}\
-(id)copyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(id)mutableCopyWithZone:(NSZone *)zone{\
return _instance;\
}\
-(void)destory{\
_instance = nil;\
onceToken = 0;\
}\
-(oneway void)release{\
}\
- (instancetype)retain{\
return _instance;\
}\
-(NSUInteger)retainCount{\
return MAXFLOAT;\
}
#endif
#endif /* Single_h */