全局单例换一种姿势使用

最近在写项目中遇到一个问题,是关于单例的问题,一般我们使用单例,其实用起来很简单,但是在某些场景下,我们目前的使用方式就会出现问题,下面我们来看看。

使用场景

首先来说一下我遇到的使用场景,有一个类,我需要在整个项目工程中,他只能被创建一次,无论用什么创建方式,他的内存地址都不能更改。

首先按照我们日常的单例使用方式,我们来实现一下。

首先有一个单例类Single

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
@interface Single : NSObject

+ (instancetype)sharedInstance;

@end

@implementation Single

+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static Single *__single = nil;
dispatch_once(&onceToken, ^{
__single = [[Single alloc] init];
});
return __single;
}

- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
return self;
}

@end

我们每次获取这个类使用的时候,直接使用sharedInstance获取,这样不用说,获取出来的肯定是同一个对象

但是现在我的这个类对外提供了一个初始化方法

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
@interface Single : NSObject

@property (nonatomic, copy) NSString *key;

+ (instancetype)sharedInstance;

- (instancetype)initWithKey:(NSString *)key;

@end

-----------------------------------------------------------------------------

@implementation Single

+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static Single *__single = nil;
dispatch_once(&onceToken, ^{
__single = [[Single alloc] init];
});
return __single;
}

- (instancetype)init {
return [self initWithKey:nil];
}

- (instancetype)initWithKey:(NSString *)key {
self = [super init];
if (!self) {
return nil;
}
_key = [key copy];
return self;
}

@end

然后我在需要使用到single的地方这样来获取

1
2
Single *single1 = [Single sharedInstance];
Single *single2 = [[Single alloc] initWithKey:@"11"];

打印出他们的内存地址

1
2
3
4
Printing description of single1:
<Single: 0x60000000d610>
Printing description of single2:
<Single: 0x60000000d5f0>

很明显,我现在得到的是两个不一样的对象,我想要获得完全一样的对象,怎么做呢

解决方法

每个对象在初始化的时候,都是先获取内存地址,而这一步是在方法

1
+ (instancetype)allocWithZone:(struct _NSZone *)zone;

在我们的init方法中,都是在做一些让这个对象能满足我们使用的一些设置

那我想要在整个工程中获取到唯一的一个实例,我们就可以在这个分配内存的方法中做单例步骤

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
@implementation Single

+ (instancetype)sharedInstance {
return [[self alloc] init];
}

- (instancetype)init {
return [self initWithKey:nil];
}

- (instancetype)initWithKey:(NSString *)key {
self = [super init];
if (!self) {
return nil;
}
_key = [key copy];
return self;
}

static Single *__single = nil;
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__single = [super allocWithZone: zone];
});
return __single;
}

@end

我们再次获取使用单例时

1
2
3
4
Single *single1 = [Single sharedInstance];
Single *single2 = [[Single alloc] initWithKey:@"11"];
Single *single3 = [Single sharedInstance];
Single *single4 = [[Single alloc] init];

得到的完全是相同的一个实例

1
2
3
4
5
6
7
8
Printing description of single1:
<Single: 0x6000000155d0>
Printing description of single2:
<Single: 0x6000000155d0>
Printing description of single3:
<Single: 0x6000000155d0>
Printing description of single4:
<Single: 0x6000000155d0>

欢迎关注微博:ppsheep_Qian

http://weibo.com/ppsheep

欢迎关注公众号