1.ios的单例模式有两种官方写法:
1)不使用GCD的方式
#import "Manager.h"
static Manager *manager;
@implementation Manager
+(Manager *))shareManager {
if (!manager) {
manager = [super allocWithZone:NULL] init];
}
return manager;
}
@end;
2)使用GCD的方式
#import "Manager.h"
@implementataion Manager
+(Manager *)shareManager {
static Manager *shareManager;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
shareManager =[super allocWithZone:NULL] init];
});
return shareManager;
}
//注明:dispatch_once这个函数,他可以一次保证整个应用程序生命周期中某段代码只被执行
//不是使用alloc 方法,而是调用[super allocWithZone:NULL] init]; 已经重载allocWithZone基本的对象分配方法,所以要借用父类(NSObject)的功能来帮助处理底层内存分配的杂物
当我们调用shareManager方法时获取到的对象是相同的,但是但当我们通过alloc和init以及copy来构造对象依然会创建新的实例。确保对象的唯一,需要封锁用户通过alloc和init以及copy来构造这条道路。创建对象的步骤分为申请内存(alloc)、初始化(init),要确保对象的唯一性,在第一步这个阶段我们就要拦截它,当我们调用alloc方法时,oc内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法调用shareManager返回单例对象。
+(id)allocWithZone:(struct _NSZone *)zone {
return [Manager shareManager];
}
-(id)copyWithZone:(NSZone *)zone {
return [Manager shareManager];
}
-(id)mutablecopyWithZone:(NSZone *)zone {
return [Manager shareManager];
}
@end
2.alloc和allocWithZone
在初始化一个对象时([Class alloc] init];)其实做了两件事,alloc给对象分配内存空间,init是对对象的初始化,包括设置成员变量初始值这些工作。
而给对象分配内存空间,除了alloc方法之外还有另一个方法:allocWithZone.在NSObject类的官方文档里面,allocWithZone方法介绍说,该方法的参数是被忽略的,正确的做法是传nil或者NULL参数给他。(这个方法存在是历史遗留原因,文档里memory zone已经被弃用了,只是历史原因才保留这个接口)
实践证明,alloc方法初始化一个类的实例时,默认调用allocWithZone的方法,为了保持单例实例的唯一性需要覆盖所有会生成新的实例方法,如果有人初始化这个单例的时候不走allocWithZone,而是直接[Class alloc] init]; ,那么这个单例就不再是单例了,所以把这个方法堵上
3.NSZone?
网友评论