單例模式
有時(shí)候我們需要一個(gè)全局的對(duì)象葬荷,而且要保證全局有且僅有一份即可,這時(shí)候就需要用到單例設(shè)計(jì)模式,但是需要注意的是:在多線程的環(huán)境下也需要做好線程保護(hù)。其實(shí)系統(tǒng)已經(jīng)有很多單例存在,例如UIApplication娜膘、NSNotification痕届、NSFileManager、NSUserDefaults等.以下代碼詳解
ARC環(huán)境下嚴(yán)謹(jǐn)?shù)膯卫J?/h4>
#import <Foundation/Foundation.h>
@interface JHTool : NSObject<NSCopying,NSMutableCopying>
//類方法
//1.方便訪問(wèn)
//2.標(biāo)明身份
//3.注意:share+類名|default + 類名 | share | default | 類名
+(instancetype)shareTool;
@end
#import "JHTool.h"
@implementation JHTool
//提供一個(gè)全局靜態(tài)變量
static JHTool * _instance;
+(instancetype)shareTool{
return [[self alloc]init];
}
//當(dāng)調(diào)用alloc的時(shí)候會(huì)調(diào)用allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//方案一:加互斥鎖,解決多線程訪問(wèn)安全問(wèn)題
// @synchronized(self){//同步的
// if (!_instance) {
// _instance = [super allocWithZone:zone];
// }
// }
//方案二.GCD dispatch_onec,本身是線程安全的,保證整個(gè)程序中只會(huì)執(zhí)行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//嚴(yán)謹(jǐn)
//遵從NSCopying協(xié)議,可以通過(guò)copy方式創(chuàng)建對(duì)象
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
return _instance;
}
//遵從NSMutableCopying協(xié)議,可以通過(guò)mutableCopy方式創(chuàng)建對(duì)象
- (nonnull id)mutableCopyWithZone:(nullable NSZone *)zone {
return _instance;
}
@end
#import "ViewController.h"
#import "JHTool.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
JHTool * tool1 = [[JHTool alloc]init];
JHTool * tool2 = [JHTool shareTool];
JHTool * tool3 = tool1.copy;
JHTool * tool4 = tool2.mutableCopy;
NSLog(@"tool1:%p,tool2:%p,tool3:%p,tool4:%p,",tool1,tool2,tool3,tool4);
printf("tool1:%p,tool2:%p,tool3:%p,tool4:%p,",tool1,tool2,tool3,tool4);
}
@end
打印結(jié)果:
ARC單例模式
MRC環(huán)境下嚴(yán)謹(jǐn)?shù)膯卫J?/h4>
#import <Foundation/Foundation.h>
@interface JHTool : NSObject<NSCopying,NSMutableCopying>
//類方法
//1.方便訪問(wèn)
//2.標(biāo)明身份
//3.注意:share+類名|default + 類名 | share | default | 類名
+(instancetype)shareTool;
@end
#import "JHTool.h"
@implementation JHTool
//提供一個(gè)全局靜態(tài)變量
static JHTool * _instance;
+(instancetype)shareTool{
return [[self alloc]init];
}
//當(dāng)調(diào)用alloc的時(shí)候會(huì)調(diào)用allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//方案一:加互斥鎖,解決多線程訪問(wèn)安全問(wèn)題
// @synchronized(self){//同步的
// if (!_instance) {
// _instance = [super allocWithZone:zone];
// }
// }
//方案二.GCD dispatch_onec,本身是線程安全的,保證整個(gè)程序中只會(huì)執(zhí)行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//嚴(yán)謹(jǐn)
//遵從NSCopying協(xié)議,可以通過(guò)copy方式創(chuàng)建對(duì)象
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
return _instance;
}
//遵從NSMutableCopying協(xié)議,可以通過(guò)mutableCopy方式創(chuàng)建對(duì)象
- (nonnull id)mutableCopyWithZone:(nullable NSZone *)zone {
return _instance;
}
@end
#import "ViewController.h"
#import "JHTool.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
JHTool * tool1 = [[JHTool alloc]init];
JHTool * tool2 = [JHTool shareTool];
JHTool * tool3 = tool1.copy;
JHTool * tool4 = tool2.mutableCopy;
NSLog(@"tool1:%p,tool2:%p,tool3:%p,tool4:%p,",tool1,tool2,tool3,tool4);
printf("tool1:%p,tool2:%p,tool3:%p,tool4:%p,",tool1,tool2,tool3,tool4);
}
@end
打印結(jié)果:
ARC單例模式
Xcode5以后項(xiàng)目默認(rèn)都是ARC,所以把項(xiàng)目設(shè)置成MRC環(huán)境,選擇項(xiàng)目 Target -> Build Sttings -> All -> 搜索‘Automatic’ -> 把 Objective-C Automatic Reference Counting 設(shè)置為 NO 徘公,如下圖:
項(xiàng)目設(shè)置成MRC環(huán)境
MRC單例模式代碼詳解
#import <Foundation/Foundation.h>
@interface HJTool : NSObject<NSCopying,NSMutableCopying>
//類方法
+(instancetype)shareTool;
@end
#import "HJTool.h"
@implementation HJTool
//修改環(huán)境為MRC:選擇項(xiàng)目 Target -> Build Sttings -> All -> 搜索‘Automatic’ -> 把 Objective-C Automatic Reference Counting 設(shè)置為 NO
//提供一個(gè)靜態(tài)全局變量
static HJTool * _instance;
//實(shí)現(xiàn)類方法
+(instancetype)shareTool{
return [[self alloc]init];
}
//alloc會(huì)調(diào)用allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone{
//方法一.互斥鎖保證線程安全
// @synchronized(self){
// if (_instance == nil) {
// _instance = [super allocWithZone:zone];
// }
// }
//方法一.GCD-> dispatch_once_t 該方法只會(huì)執(zhí)行一次,本身線程安全
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
-(id)copyWithZone:(NSZone *)zone{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return _instance;
}
//MRC特有的
-(instancetype)retain{
return _instance;
}
-(oneway void)release{
NSLog(@"%zd",_instance.retainCount);
}
#import "ViewController.h"
#import "HJTool.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
HJTool * t1 = [[HJTool alloc]init];
HJTool * t2 = [[HJTool alloc]init];
HJTool * t3 = [HJTool shareTool];
HJTool * t4 = [t1 copy];
HJTool * t5 = [t2 mutableCopy];
HJTool * t6 = [t1 retain];
NSLog(@"t6.retainCount : %zd",t1.retainCount);
NSLog(@"t1:%p t2:%p t3:%p t4:%p t5:%p t6:%p",t1,t2,t3,t4,t5,t6);
}
打印結(jié)果
MRC單例模式
拓展:區(qū)分是MRC還是ARC的宏
#if __has_feature(objc_arc)
//條件滿足 ARC,可以處理ARC的代碼
NSLog(@"ARC");
#else
//條件滿足 MRC,,可以處理MRC的代碼
NSLog(@"MRC");
#endif
通用的單例模式
在
SingleDog.h
文件中定義一個(gè)宏,SingleH(name)
定義單例.h文件的類方法聲明,SingleM(name)
定義和實(shí)現(xiàn)單例.m文件的方法,定義的宏的代碼如下
#define SingleH(name) +(instancetype)share##name;//.h文件替換
//.m文件替換
#if __has_feature(objc_arc)//arc
//條件滿足 ARC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}
#else
//條件滿足 MRC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
return _instance;\
}
#endif
單例
SingleTool
文件,頭文件和實(shí)現(xiàn)文件分別調(diào)用宏的SingleH(name)
,SingleM(name)
即可,代碼如下
#import <Foundation/Foundation.h>
#import "SingleDog.h"
@interface SingleTool : NSObject
//替換頭文件
SingleH(SingleTool)
@end
#import "SingleTool.h"
@implementation SingleTool
SingleM(SingleTool)
@end
#import "ViewController.h"
#import "SingleTool.h"
@interface ViewController ()
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
SingleTool * t1 = [[SingleTool alloc]init];
SingleTool * t2 = [SingleTool shareSingleTool];
SingleTool * t3 = [t1 copy];
SingleTool * t4 = [t1 mutableCopy];
#if __has_feature(objc_arc)
//條件滿足 ARC,可以處理ARC的代碼
NSLog(@"ARC");
#else
//條件滿足 MRC,,可以處理MRC的代碼
NSLog(@"MRC");
SingleTool * t5 = [t1 retain];
NSLog(@"t6.retainCount : %zd",t1.retainCount);
NSLog(@"t1:%p t2:%p t3:%p t4:%p t5:%p",t1,t2,t3,t4,t5);
#endif
}
@end
MRC環(huán)境下打印結(jié)果如下:
MRC通用單例模式