单例
#iOS 单例
##ARC方式实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47//.h文件
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
//单例方法
+(instancetype)sharedSingleton;
@end
//.m文件
#import "Singleton.h"
@implementation Singleton
//全局变量
static id _instance = nil;
//单例方法
+(instancetype)sharedSingleton{
return [[self alloc] init];
}
////alloc会调用allocWithZone:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//初始化方法
- (instancetype)init{
// 只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super init];
});
return _instance;
}
//copy在底层 会调用copyWithZone:
- (id)copyWithZone:(NSZone *)zone{
return _instance;
}
+ (id)copyWithZone:(struct _NSZone *)zone{
return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
@end
##MRC方式实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60//.m文件
#import <Foundation/Foundation.h>
//单例方法
@interface Singleton : NSObject
+ (instancetype)sharedSingleton;
@end
//.m文件
#import "Singleton.h"
@implementation Singleton
//全局变量
static id _instance = nil;
//单例方法
+(instancetype)sharedSingleton{
//系统的大多数类方法都有做autorelease,所以我们也需要做一下
return [[[self alloc] init] autorelease];
}
//alloc会调用allocWithZone:
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//初始化方法
-(instancetype)init{
// 只进行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super init];
});
return _instance;
}
- (oneway void)release{
//什么都不做 保证单例对象不被销毁
}
//返回本身 保证只有一个单例对象
- (instancetype)retain{
return _instance;
}
//计数器为1 保证只有一个单例对象
- (NSUInteger)retainCount{
return 1;
}
//copy在底层 会调用copyWithZone:
+ (id)copyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)copyWithZone:(NSZone *)zone{
return _instance;
}
+ (id)mutableCopyWithZone:(struct _NSZone *)zone{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
@end
##dispatch_once用来做单例是效果最好的
dispatch_once为什么能做到既解决同步多线程问题又不影响性能呢?
下面我们来看看dispatch_once的原理:
dispatch_once主要是根据onceToken的值来决定怎么去执行代码。
当onceToken= 0时,线程执行dispatch_once的block中代码
当onceToken= -1时,线程跳过dispatch_once的block中代码不执行
当onceToken为其他值时,线程被线程被阻塞,等待onceToken值改变
当线程首先调用shareInstance,某一线程要执行block中的代码时,首先需要改变onceToken的值,再去执行block中的代码。这里onceToken的值变为了140734731430192。
这样当其他线程再获取onceToken的值时,值已经变为140734731430192。其他线程被阻塞。
当block线程执行完block之后。onceToken变为-1。其他线程不再阻塞,跳过block。
下次再调用shareInstance时,block已经为-1。直接跳过block。
这样dispatch_once在首次调用时同步阻塞线程,生成单例之后,不再阻塞线程。dispatch_once是创建单例的最优方案
##避免滥用单例
http://www.cocoachina.com/industry/20140615/8830.html