单例模式 - GCD、兼容ARC和MRC
单例模式的作用:
1,可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问
2,从而方便地控制了实例个数,并节约系统资源
单例模式的使用场合:
在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次)
单例模式在ARC\MRC环境下的写法有所不同,需要编写2套不同的代码
可以用宏判断是否为ARC环境
#if __has_feature(objc_arc)
//ARC
#else
//MRC
#endif
在游戏中,音乐在不同的场景可能相同,我们应该只要创建一份,这时候我们就应该使用单例模式,可以节省内存;
在ARC环境下,实现单例模式: 代码如下:
要使得他们alloc init一份,就可以使用GCD的dispatch_once,还可以保证线程安全;
#import "HMAudioTool.h"
@interface HPAudioTool()
@end
@implementation HPAudioTool
//// 定义一份变量(整个程序运行过程中,只有1份)
static id _instance;
- (id)init
{
if (self = [super init]) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//加载资源
});
}
return self;
}
/**
* 重写这个方法 :控制内存内存
*/
+ (id)allocWithZone:(struct _NSZone *)zone
{
// 里面的代码永远只执行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
//返回对象
return _instance;
}
+ (instancetype)sharedAudioTool
{
// 里面的代码永远只执行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
//返回对象
return _instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone
{
return _instance;
}
@end
那么在MRC中呢?那当然就要考虑内存的释放了;必须要release了;
然而在release方法中,会调用[super release];
还有autorelease,retain,retainCount,copyWithZone;都得保证调用一次;
代码如下:
@interface HPAudioTool()
@end
@implementation HPAudioTool
//// 定义一份变量(整个程序运行过程中,只有1份)
static id _instance;
- (id)init
{
if (self = [super init]) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//加载资源
});
}
return self;
}
/**
* 重写这个方法 :控制内存内存
*/
+ (id)allocWithZone:(struct _NSZone *)zone
{
// 里面的代码永远只执行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
//返回对象
return _instance;
}
+ (instancetype)sharedAudioTool
{
// 里面的代码永远只执行1次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
//返回对象
return _instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone
{
return _instance;
}
- (oneway void)release
{
}
- (id)autorelease
{
return _instance;
}
- (id)retain
{
return _instance;
}
- (NSUInteger)retainCount
{
return 1;
}
+ (id)copyWithZone:(struct _NSZone *)zone
{
return _instance;
}
@end
当然我们在使用过程中,我们可以把这些代码写成宏,使用起来方便,便于修改;
为了兼容ARC和MRC,我们可以将代码合并如下:
// ## :连接字符串和参数
#define singleton_h(name) + (instancetype)shared##name;
#if __has_feature(objc_arc) // ARC
#define singleton_m(name) \
static id _instance; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[self alloc] init]; \
})\
return _instance; \
} \
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instance; \
}
#else //非ARC
#define singleton_m(name) \
static id _instance; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[self alloc] init]; \
}); \
return _instance; \
} \
\
- (oneway void)release \
{ \
\
} \
\
- (id)autorelease \
{ \
return _instance; \
} \
\
- (id)retain \
{ \
return _instance; \
} \
\
- (NSUInteger)retainCount \
{ \
return 1; \
} \
\
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instance; \
}
#endif
然后大家直接可以拷贝走,直接拿去调用;