iOS 单例模式使用
2016-06-23 本文已影响114人
苏宇lovecc
注:只介绍怎么使用,至于其他的方面,google去吧。
-
实现步骤:
- 为单例对象声明一个静态实例,并初始化,然后设置成nil。
- 声明并实现一个类方法,检查上面声明的静态实例是否为nil;如果是,则将静态变量初始化为本类的实例。
- 重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不会产生一个新实例。
- 非ARC(MRC)模式下,实现copyWithZone,release和autorelease等方面。
-
具体代码
具体的实现方法有2种。假设有个类UserInfo需要使用单例模式。
首先,在UserInfo.h
文件中,需要提供一个标准的实例访问接口。
//该类方法的名称一般以 share,default,main为前缀
+(UserInfo *)shareUserInfo;
第1种方法:
#import "UserInfo.h"
//定义一个静态变量,用于接收实例对象并初始化为nil
static UserInfo *singleInstance = nil;
@implementation UserInfo
//在多线程的情况下,多个任务会同时执行,它们的执行方式是抢占式的,所以为保证线程安全,增加互斥锁
+ (UserInfo *)shareUserInfo {
@synchronized (self) {
if (singleInstance == nil) {
singleInstance = [[UserInfo alloc] init];
}
}
return singleInstance;
}
//使用单例时,不想再实例化出其它的对象,可以重写 allocWithZone:
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
@synchronized (self) {
if (singleInstance == nil) {
singleInstance = [super allocWithZone:zone];
}
}
return singleInstance;
}
@end
第2种方法:
#import "UserInfo.h"
static UserInfo *singleInstance = nil;
@implementation UserInfo
//1.dispatch_once可以在创建单例或者某些初始化动作时使用,以保证其唯一性。
//2.该方法是线程安全的,所以请放心大胆地在子线程中使用。前提是你的dispatch_once_t *predicate对象必须是全局或者静态对象。这一点很重要,如果不能保证这一点,也就不能保证该方法只会被执行一次。
+ (UserInfo *)shareUserInfo {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleInstance = [[UserInfo alloc] init];
});
return singleInstance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleInstance = [super allocWithZone:zone];
});
return singleInstance;
}
@end
另外,在非ARC(MRC)模式下,需要重写以下方法
//禁止copy
+(id)copyWithZone:(struct _NSZone *)zone{
return self;
}
//retain后引用计数+1
-(instancetype)retain{
return self;
}
//release后引用计数-1
-(oneway void)release{
//什么都不做
}
//自动释放池
-(instancetype)autorelease{
return self;
}
//查看引用计数器
-(NSUInteger)retainCount{
//返回无穷大的数,表示不能release
return NSIntegerMax;
}