這是我之前不嚴謹?shù)膭?chuàng)建單例的寫法
.h
@interface MySingle : NSObject
+ (instancetype)shareInstance;
@end
.m
+ (instancetype)shareInstance
{
static MySingle *_mySingle = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_mySingle = [[MySingle alloc] init];
});
return _mySingle;
}
這種寫法有問題呀,雖然只提供了一種初始化方式斧散,但你不能阻止別人用 [[xxx alloc] init]
,初始化呀。
下面是測試的例子
MySingle *single01 = [MySingle shareInstance];
NSLog(@"single 01 = %@",single01);
MySingle *single02 = [MySingle shareInstance];
NSLog(@"single 02 = %@",single02);
MySingle *single03 = [[MySingle alloc] init];
NSLog(@"single 03 = %@",single03);
輸出
2018-01-08 16:16:42.844100+0800 單例測試[6605:444452] single 01 = <MySingle: 0x60400020b1a0>
2018-01-08 16:16:42.844310+0800 單例測試[6605:444452] single 02 = <MySingle: 0x60400020b1a0>
2018-01-08 16:16:42.844815+0800 單例測試[6605:444452] single 03 = <MySingle: 0x60400020b2e0>
通過上面的測試,可以看到通過shareInstance
方法獲取的對象是相同的菠红,但是用alloc
和init
構(gòu)造對象時律杠,得到的對象卻是不一樣的潭流。
通過不同的方式獲得不同的對象,是有問題的柜去,所以要封鎖初始化的方式灰嫉,如alloc
copy
mutableCopy
還有一個new
下面是我摘抄的原理哈
創(chuàng)建對象的步驟分為申請內(nèi)存(alloc)、初始化(init)這兩個步驟嗓奢,我們要確保對象的唯一性讼撒,因此在第一步這個階段我們就要攔截它。當我們調(diào)用alloc方法時股耽,OC內(nèi)部會調(diào)用allocWithZone這個方法來申請內(nèi)存根盒,我們覆寫這個方法,然后在這個方法中調(diào)用shareInstance方法返回單例對象物蝙,這樣就可以達到我們的目的炎滞。拷貝對象也是同樣的原理诬乞,覆寫copyWithZone方法册赛,然后在這個方法中調(diào)用shareInstance方法返回單例對象
下面是改良后的代碼
MySingle2
#import "MySingle2.h"
@implementation MySingle2
+(instancetype)shareInstance
{
static MySingle2 *_mySingle = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_mySingle = [[super allocWithZone:NULL] init];
});
return _mySingle;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
return [self shareInstance];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return self;
}
再放上測試代碼
MySingle2 *single01 = [MySingle2 shareInstance];
NSLog(@"single 01 = %@",single01);
MySingle2 *single02 = [MySingle2 shareInstance];
NSLog(@"single 02 = %@",single02);
MySingle2 *single03 = [[MySingle2 alloc] init];
NSLog(@"single 03 = %@",single03);
NSLog(@"copy = %@",[single03 copy]);
MySingle2 *single04 = [MySingle2 new];
NSLog(@"new = %@",single04);
輸出
// 2018-01-08 16:56:26.973122+0800 單例測試[7195:493942] single 01 = <MySingle2: 0x604000017360>
// 2018-01-08 16:56:26.973357+0800 單例測試[7195:493942] single 02 = <MySingle2: 0x604000017360>
// 2018-01-08 16:56:26.973630+0800 單例測試[7195:493942] single 03 = <MySingle2: 0x604000017360>
// 2018-01-08 16:56:26.973808+0800 單例測試[7195:493942] copy = <MySingle2: 0x604000017360>
// 2018-01-08 16:56:26.973952+0800 單例測試[7195:493942] new = <MySingle2: 0x604000017360>
ok 不管用哪種方式 初始化 獲得的對象都是一樣的,這樣就達到我們單例的目的了丽惭。
你以為到這就結(jié)束了击奶,嘿嘿,且看下面
做一點小修改
#import "MySingle3.h"
@implementation MySingle3
static MySingle3 *_mySingle = nil;
+(instancetype)shareInstance
{
if (_mySingle == nil) {
_mySingle = [[MySingle3 alloc] init];
}
return _mySingle;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_mySingle = [super allocWithZone:zone];
});
return _mySingle;
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return self;
}
@end
下面的寫法我感覺比較自然點责掏,就是換了一個樣子初始化柜砾。
有沒有發(fā)現(xiàn),如果寫單例换衬,都要寫這么一堆代碼痰驱,豈不是很繁瑣。
可以寫成宏的方式瞳浦,寫成一個文件担映,直接調(diào)用,即可叫潦。
廢話不多說了蝇完,直接上代碼
這是調(diào)用方式
.h
#import <Foundation/Foundation.h>
#import "Single.h"
@interface MySingle4 : NSObject
SingleInterface(MySingle4);
@end
.m
@implementation MySingle4
SingleImplementation(MySingle4);
@end
好吧,再把測試代碼也貼出來
MySingle4 *single01 = [MySingle4 shareMySingle4];;
NSLog(@"single 01 = %@",single01);
MySingle4 *single02 = [MySingle4 shareMySingle4];
NSLog(@"single 02 = %@",single02);
MySingle4 *single03 = [[MySingle4 alloc] init];
NSLog(@"single 03 = %@",single03);
NSLog(@"copy = %@",[single03 copy]);
MySingle4 *single04 = [MySingle4 new];
NSLog(@"new = %@",single04);
輸出
2018-01-08 17:31:56.844532+0800 單例測試[7726:530743] single 01 = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.844795+0800 單例測試[7726:530743] single 02 = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.845013+0800 單例測試[7726:530743] single 03 = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.845225+0800 單例測試[7726:530743] copy = <MySingle4: 0x600000009b00>
2018-01-08 17:31:56.845471+0800 單例測試[7726:530743] new = <MySingle4: 0x600000009b00>