本文共 2071 字,大约阅读时间需要 6 分钟。
static Manager *manager;@implementation Manager+ (Manager *)sharedManager { if(!manager) { manager=[[self allocWithZone:NULL] init]; } return manager;}+ (id)allocWithZone:(NSZone *)zone { return [[self sharedManager] retain];}@end
注意: 此代码只适用于单线程,如果在多线程中使用将会创建多个实例
#import "Manager.h"@implementation Manager+ (Manager *)sharedManager { static dispatch_once_t onceToken; static Manager *sharedManager; dispatch_once(&onceToken, ^{ sharedManager=[[Manager alloc] init]; }); return sharedManager;}@end
注: dispatch_once 无论使用多线程还是单线程,都只执行一次, 在安全的前提下也保证了性能, 是官方推荐的方式.
dispatch_once 主要是根据onceToken 的值来决定怎么去执行代码
dispatch_once 执行的流程:
问题来源于上文不使用GCD的单例代码实现
有人提出:为什么要覆盖allocWithZone:方法,到底 alloc 和 allocWithZone: 有什么区别呢首先我们知道,我们需要保证单例类只有一个唯一的实例,而平时我们在初始化一个对象的时候, [[Class alloc] init],其实是做了两件事:alloc 给对象分配内存空间,init是对对象的初始化,包括设置成员变量初值这些工作。而给对象分配空间,除了alloc方法之外,还有另一个方法: allocWithZone:
在NSObject 这个类的官方文档里面,allocWithZone:方法介绍说,该方法的参数是被忽略的,正确的做法是传nil或者NULL参数给它。而这个方法之所以存在,是历史遗留原因
而实践证明,使用alloc方法初始化一个类的实例的时候,默认是调用了 allocWithZone: 的方法。于是覆盖allocWithZone:方法的原因已经很明显了:为了保持单例类实例的唯一性,需要覆盖所有会生成新的实例的方法,如果有人初始化这个单例类的时候不走[[Class alloc] init] ,而是直接 allocWithZone:, 那么这个单例就不再是单例了,所以必须把这个方法也堵上转载地址:http://okkti.baihongyu.com/