单例模式是一种很重要的设计模式,在iOS开发中,通过使用单例设计模式来实现在程序生命周期内只有一个实例存在来节省内存开销。
下面是ARC中单例模式的实现代码:
在自定义的类.m文件中,需要实现下列的方法
#import
"HMAudioTool.h"
@interface HMAudioTool ()
@end
@implementation HMAudioTool
定义一份变量 ( 整个程序运行过程中 , 只有 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 ;
}
@interface HMAudioTool ()
@end
@implementation HMAudioTool
定义一份变量 ( 整个程序运行过程中 , 只有 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 ;
}
@end
通过重写allocWithZone,copyWithZone,以及init方法来实现在内存中只存在一个HMAudioTool对象.
上面的代码是ARC下单例的实现,而对于非ARC而言,还需要重写release,autorelease,retain,retainCount来保证返回的对象为单例,代码如下:
+ (
id
)copyWithZone:(
struct
_NSZone
*)zone
{
return _instance ;
}
- ( oneway void )release
{
}
- ( instancetype )autorelease
{
return _instance ;
}
- ( instancetype )retain
{
return _instance ;
}
- ( NSUInteger )retainCount
{
return 1 ;
{
return _instance ;
}
- ( oneway void )release
{
}
- ( instancetype )autorelease
{
return _instance ;
}
- ( instancetype )retain
{
return _instance ;
}
- ( NSUInteger )retainCount
{
return 1 ;
}
通过重写上面五个方法来确保单例对象在非ARC下存在。
实际开发中,我们可以将这些代码抽取到一个头文件里面以宏定义的方式来调用.
// ## : 连接字符串和参数
#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