单例设计模式确切的说就是一个类只有一个实例,有一个全局的接口来访问这个实例。当第一次载入的时候,它通常使用延时加载的方法创建单一实例。
苹果大量的使用了这种方法。例子: [UIApplication sharedApplication], [UIScreen mainScreen], [UIApplication sharedApplication]; (应用程序实例类);[NSNotificationCenter defaultCenter];(消息中心实例类);[NSFileManager defaultManager];(文件管理实例类);[NSUserDefaults standardUserDefaults];(应用程序设置);[NSURLCache sharedURLCache];(请求缓存实例类)。一般在程序中,经常调用的类,如工具类、公共跳转类等都会采用单例模式,都返回一个单一对象。
单例类,在整个项目中只有一个实例,并提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序退出时由系统自动释放这部分内存。
在程序中,一个单例类在程序中只能初始化一次,为了保证在使用中始终都是存在的,所以单例是在存储器的全局区域,在编译时分配内存,只要程序还在运行就会一直占用内存,在APP结束后由系统释放这部分内存内存。
单例的实现:
为单例对象创建一个静态实例,可以写成全局的,也可以在类方法里面实现,并初始化为nil;实现一个实例构造方法,检查上面声明的静态实例是否为nil,如果是,则创建并返回一个本类的实例;重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例; 适当实现copyWithZone,mutableCopyWithZone,非arc下还需要实现release和autorelease方法。
iOS单例的创建分为两种模式:ARC和MRC
ARC下单例的创建:
- 先定义一个静态的instance. static MyClass _instance;
- 重写allocWithZone方法.此方法为对象分配空间必须调用方法.
- 定一个个share的类方法.能够被全局调用的.此方法里需要考虑线程安全问题
- 如果需要copy,需要遵守NSCopying协议,以及在copyWithZone中,直接返回self;
static Myclass _instance;
方法一:
+(id)shareInstance{
@synchronized(self){
if(_instance == nil)
_instance = [MyClass alloc] init];
}
return _instance;
}
方法二:
+(id)shareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(_instance == nil)
_instance = [MyClass alloc] init];
});
return _instance;
}
以上两种方法都是线程安全的.不过苹果官方现在提倡方法二.
MRC下单例的创建,创建过程跟ARC下步骤一样.不过要处理一些内存管理的函数:
//不需要计数器+1
- (id)retain {
return self;
}
//不需要. 堆区的对象才需要
- (id)autorelease {
return self;
}
//不需要
- (oneway void)release {
}
//不需要计数器个数. 直接返回最大无符号整数
- (NSUInteger)retainCount {
return UINT_MAX; //参照常量区字符串的retainCount
}
这样就能保证这个单例不会被无意释放。