单例模式的作用:可以保证在程序运行过程,一个类只有一个实例,而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源。
单例模式的使用场合: 在整个应用程序中,共享一份资源(这份资源只需要创建初始化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);
~~~
![](https://box.kancloud.cn/2016-03-07_56dd40104f8b1.jpg)
##三:单例模式在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);
~~~
![](https://box.kancloud.cn/2016-03-07_56dd40106ce82.jpg)
- 前言
- 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加密