單例模式的作用:可以保證在程序運行過程,一個類只有一個實例,而且該實例易于供外界訪問,從而方便地控制了實例個數,并節約系統資源。
單例模式的使用場合:?在整個應用程序中,共享一份資源(這份資源只需要創建初始化1次)。
##一:單例模式 - ARC:
1、在.m中保留一個全局的static的實例(static 防止其它類extern引用 修改值)
staticid _instance;
2、重寫allocWithZone:方法,在這里創建唯一的實例(注意線程安全)
~~~
+ (id)allocWithZone:(struct_NSZone *)zone {
? ? if (_instance ==nil) { //防止頻繁加鎖
? ? ? ?@synchronized(self) {
? ? ? ? ? ?if (_instance ==nil) { //防止創建多次
? _instance = [superallocWithZone:zone];
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return_instance;
}
~~~
3、提供1個類方法讓外界訪問唯一的實例
~~~
+ (instancetype)sharedMusicTool {
? ? if (_instance ==nil) { //防止頻繁加鎖
? ? ? ?@synchronized(self) {
? ? ? ? ? ?if (_instance ==nil) { //防止創建多次
?? ? ? ? ? ? ?_instance = [[selfalloc] init];
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return_instance;
}
~~~
4、實現copyWithZone:方法
~~~
- (id)copyWithZone:(struct_NSZone *)zone {
? ? return_instance;
}
~~~
5、如果要實現餓漢式的單例,就實現load方法。(建議不使用)
//當類加載到OC運行時環境中(內存),就會調用一次(一個類只會加載1次)
~~~
+(void)load{
? ? _instance = [[self alloc] init];
}
~~~
音樂單例工具類例子代碼:
MusicTool.h
~~~
#import <UIKit/UIKit.h>
@interface MusicTool : UIView
//提供1個類方法讓外界訪問唯一的實例
+(instancetype)sharedMusicTool;
@end
~~~
MusicTool.m
~~~
#import "MusicTool.h"
//單例模式:懶漢式
@implementation MusicTool
static id _instance; //static 防止其它類extern引用 修改值
/**
* 如果要實現餓漢式的單例,就實現load方法
* 當類加載到OC運行時環境中(內存),就會調用一次(一個類只會加載1次)
*/
//+(void)load{
// _instance = [[self alloc] init];
//}
//當第一次使用這個類的時候才會調用
//+(void)initialize{
// NSLog(@"===initialize===");
//}
/**
* alloc 方法內部會調用這個方法
*/
+(id)allocWithZone:(struct _NSZone *)zone{
if (_instance == nil) {//防止頻繁加鎖
@synchronized(self) {
if (_instance == nil) {//防止創建多次
_instance = [super allocWithZone:zone];
}
}
}
return _instance;
}
/**
* 實例化類
*/
+(instancetype)sharedMusicTool{
if (_instance == nil) {//防止頻繁枷鎖
@synchronized(self) {
if (_instance == nil) {//防止創建多次
_instance = [[self alloc] init ];
}
}
}
return _instance;
}
/**
* 重寫copy方法,保證copy出來的也是單例類
*/
-(id)copyWithZone:(NSZone *)zone{
return _instance;
}
@end
~~~
##二:單例模式 – 非ARC
非ARC中(MRC),單例模式的實現(比ARC多了幾個步驟)
實現內存管理方法
~~~
- (id)retain {returnself; }
- (NSUInteger)retainCount {return1; }
- (onewayvoid)release {}
- (id)autorelease {returnself; }
~~~
MusicTool.m
~~~
#import "MusicTool.h"
@implementation MusicTool
static id _instance; //static 防止其它類extern引用 修改值
/**
* 如果要實現餓漢式的單例,就實現load方法
* 當類加載到OC運行時環境中(內存),就會調用一次(一個類只會加載1次)
*/
//+(void)load{
// _instance = [[self alloc] init];
//}
//當第一次使用這個類的時候才會調用
//+(void)initialize{
// NSLog(@"===initialize===");
//}
/**
* alloc 方法內部會調用這個方法
*/
+(id)allocWithZone:(struct _NSZone *)zone{
if (_instance == nil) {//防止頻繁加鎖
@synchronized(self) {
if (_instance == nil) {//防止創建多次
_instance = [super allocWithZone:zone];
}
}
}
return _instance;
}
/**
* 實例化類
*/
+(instancetype)sharedMusicTool{
if (_instance == nil) {//防止頻繁枷鎖
@synchronized(self) {
if (_instance == nil) {//防止創建多次
_instance = [[self alloc] init ];
}
}
}
return _instance;
}
/**
* 重寫copy方法,保證copy出來的也是單例類
*/
-(id)copyWithZone:(NSZone *)zone{
return _instance;
}
//重寫release方法,不釋放
-(oneway void)release{
}
//重寫retain方法,返回單例類
-(instancetype)retain{
return self; //return _instance;
}
//計算永遠為1
-(NSUInteger)retainCount{
return 1;
}
@end
~~~
測試:
~~~
MusicTool *mt1 = [[MusicTool alloc] init];
MusicTool *mt2 = [MusicTool sharedMusicTool];
MusicTool *mt3 = [mt2 copy];
[mt2 release];//非arc環境下release
NSLog(@"==%@==%@==%@",mt1,mt2,mt3);
~~~

##三:單例模式在ARC\MRC環境下的寫法有所不同,可以用宏判斷是否為ARC環境
~~~
#if __has_feature(objc_arc)
// ARC
#else
// MRC
#endif
~~~
把單例定義成宏,抽出公共類
1、HMSingleton.h
~~~
// .h文件
#define HMSingletonH(name) + (instancetype)shared##name;
// .m文件
#if __has_feature(objc_arc)
#define HMSingletonM(name) \
static id _instace; \
\
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \
return _instace; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [[self alloc] init]; \
}); \
return _instace; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instace; \
}
#else
#define HMSingletonM(name) \
static id _instace; \
\
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [super allocWithZone:zone]; \
}); \
return _instace; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instace = [[self alloc] init]; \
}); \
return _instace; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instace; \
} \
\
- (oneway void)release { } \
- (id)retain { return self; } \
- (NSUInteger)retainCount { return 1;} \
- (id)autorelease { return self;}
#endif
~~~
2、要想再整個項目中都能使用這個宏,則要在預編譯pch文件中import導入這個頭文件
~~~
#ifdef __OBJC__
? ? #import <UIKit/UIKit.h>
? ? #import <Foundation/Foundation.h>
#import"HMSingleton.h"
#endif
~~~
? ? ps:xcode7添加pch文件參考之前的文章[http://blog.csdn.net/zhixinhuacom/article/details/49564315](http://blog.csdn.net/zhixinhuacom/article/details/49564315)
3、使用HMSingleton工具類,實現HMMusicTool單例
HMMusicTool.h
~~~
#import <Foundation/Foundation.h>
@interface HMMusicTool : NSObject
//宏定義的方法
HMSingletonH(MusicTool)
@end
~~~
HMMusicTool.m
~~~
#import "HMMusicTool.h"
@implementation HMMusicTool
//宏定義的方法
HMSingletonM(MusicTool)
@end
~~~
4.測試:
~~~
HMMusicTool *tool1 = [HMMusicTool sharedMusicTool];
HMMusicTool *tool2 = [HMMusicTool sharedMusicTool];
HMMusicTool *tool3 =[[HMMusicTool alloc]init];
HMMusicTool *tool4 =[tool3 copy];
NSLog(@"%@", tool1);
NSLog(@"%@", tool2);
NSLog(@"%@", tool3);
NSLog(@"%@", tool4);
~~~

- 前言
- iOS開發實踐之SQLite3
- iOS開發實踐之FMDB
- Obj-C與javascript交互之WebViewJavascriptBridge
- iOS開發實踐之UIWebView
- iOS開發實踐之多線程(基本概念)
- iOS開發實踐之多線程(NSThread)
- iOS開發實踐之多線程(GCD)
- iOS開發實踐之多線程(單例模式)
- iOS開發實踐之xib加載注意問題
- iOS開發實踐之多線程(NSOperation)
- iOS開發實踐之cell下載圖片(NSOperation)
- iOS開發實踐之cell下載圖片(自定義NSOperation)
- iOS開發實踐之cell下載圖片(SDWebImage)
- iOS開發實踐之JSON
- iOS開發實踐之XML
- iOS開發實踐之GET和POST請求
- iOS開發實踐之網絡檢測Reachability
- iOS開發實踐之MD5加密