单例模式
一 使用单例模式的目的:
保证内存中永远只有类的单个实例。
二 单例的建立方法:
1.声明一个静态成员变量,记录唯一实例。
2.重写allocWithZone方法,这个方法是给对象分配内存空间,最终会调用的方法,重写该方法保证只会给对象分配一个内存空间。如果考虑到多线程的情况,我们可以使用dispatch_once_t,从而保证在多线程的情况下,都只会实例化一个对象副本。
3.建立sharedXXX类方法,这样可以便于其它类访问。
三 以卖票为例,说明建立单例的步骤
首先在.m文件中申明一个静态成员变量,static id *sharedInstance;
重写allocWithZone方法,使用内存地址实例化对象,所有实例化方法,最终都会调用此方法,然后用一个变量记录第一个实例化出来的对象。
+(id)allocWithZone:(NSZone*)zone
{
static dispatch_once_t onceToken;
dispatch_once_t(&onceToken,^{
_sharedInstance=[super allocWithZone:zone];
});
return _sharedInstance;
}
然后建立一个单例类方法,便于其他类调用
+(id)sharedInastance
{
static dispatch_once_t onceToken;
dispatch_once_t(&onceToken,^{
_sharedInstance=[[self alloc]init];
});
return _sharedInstance;
}
注意:仅仅使用单例无法解决多线程中争夺资源的问题,使用同步锁@synchronized可以保证多个线程不会使用同一个代码块,而且比NSLock具有更好的性能。其次,为了保证属性安全,被争夺的资源的这个属性应该设置为原子属性atomic.但是,使用 原子属性atomic会降低系统的性能。
单例的完善--GCD方式单例
一 如果我们在一个类想在另一个类访问它的全局变量,可使用extern,引用某个全局变量(并非定义),例如:extern id _instance;
二 对static的理解
static修饰去全局变量,则全局变量的作用域仅限于当前文件内部。当我们在声明全局变量的时候,尽量使用static,这样可以防止被其他文件恶意修改。
+(id)allocWithZone:(NSZone*)zone
{
if(_instance==nil)//防止频繁加锁
{
@synchronized(self)
{
if(_instance==nil)//防止创建多次
{
_instance=[super allocWithZone:zone];
}
}
}
reutrn _instance;
}
下面是类方法,供其他类调用
+(id)sharedInastance
{
if(_instance==nil)//防止频繁加锁
{
@synchronized(self)
{
if(_instance==nil)//防止创建多次
{
_instance=[[self alloc]init];
}
}
}
reutrn _instance;
}
-(id)copyWithZone:(NSZone*)zone
{
return _instance;
}
单例的简化 ———宏实现单例
一 新建单例头文件
singleton.h
二 在singleton.h实现.h和.m的宏定义,如下图:
注意!!!在最后一行,请勿再加“\” !!!!!
三:如果单例在整个项目都用的上,可以把它放在.pch文件中,同时还的注意:使用宏实现单例,必须保证宏定义之前的的内容经过调试并且没有错误!!