什么是单例模式
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
类的创建
.m文件
static KeepFreshManage *manageCustom;
@implementation KeepFreshManage
- (instancetype) sharedLeton {
if (! manageCustom) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manageCustom = [KeepFreshManage new];
});
}
return manageCustom;
}
加上static关键字,这个全局变量 manageCustom从所有文件访问变成只有这个源文件能访问
然后我们写一个类方法,提供这个实例对象的初始化方法。
锁的比较
@implementation Singleton
- (instancetype)shareInstance
{
static Singleton* single;
@synchronized(self){
if (!single) {
single = [[Singleton alloc] init];
}
}
return single;
}
@end
这样也能保证创建唯一实例,但缺点很明显,实例创建只创建一次,这样一来,实例已经创建了,但是还是会加锁影响性能。
dispatch_once
dispatch_once主要是根据onceToken的值来决定怎么去执行代码。
当onceToken = 0时,线程执行dispatch_once的block中代码
当onceToken = -1时,线程跳过dispatch_once的block中代码不执行
当onceToken为其他值时,线程被线程被阻塞,等待onceToken值改变
当线程首先调用sharedLeton,某一线程要执行block中的代码时,首先需要改变onceToken的值,再去执行block中的代码。这里onceToken的值变为了140734731430192。
这样当其他线程再获取onceToken的值时,值已经变为140734731430192。其他线程被阻塞。
当block线程执行完block之后。onceToken变为-1。其他线程不再阻塞,跳过block。
下次再调用sharedLeton时,block已经为-1。直接跳过block。
这样dispatch_once在首次调用时同步阻塞线程,生成单例之后,不再阻塞线程。dispatch_once是创建单例的最优方案
指针置nil
通过类方法返回的对象,如果我们将上面的manageCustom置为nil了,创建的对象是否会释放呢?
答案是否定的,因为对象是作为类方法的返回值return的,会加入到自动释放池中,我们如果模拟一下,自己写过置nil的方法:
在创建了对象后,使用上面这个方法,对象就没有持有者,但是作为返回值,相当于:MRC下进行了一次retain,为了超出变量作用域依然存在,执行了autorelease方法,而不是release,所以对象不回被释放。
正确的写法
我们需要复写一些创建实例的方法来保证外部只能调用我们提供的方法来创建实例,例如alloc、copy、mutablecopy、new等,但一般不复写alloc方法。
因为一般的个人项目,我们都熟悉自己写的代码,不会胡乱调用,但是上面的写法还是有缺陷,下面补充正确的写法
static Father * manageCustom;
+ (instancetype)sharedLeton {
static dispatch_once_t onceToken;
if (!manageCustom) {
dispatch_once(&onceToken, ^{
manageCustom = [[super allocWithZone:NULL] init] ;
});
}
return manageCustom;
}
+(id) allocWithZone:(struct _NSZone *)zone
{
return [Father sharedLeton] ;
}
-(id) copyWithZone:(struct _NSZone *)zone
{
return [Father sharedLeton] ;
}
代理模式
代理,又称委托代理(delegate),是iOS中常用的设计一种模式。顾名思义,它是把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理,代替它来打理要做的事。反映到程序中, 首先要明确一个对象的委托方是哪个对象,委托所做的内容是什么。在iOS程序设计中,委托通过一种@protocol的方式实现,所以又称为协议。在iOS的SDK里面,UITableView、UITextField等都有用到这种设计模式。
协议,是多个类共享的一个方法列表,在协议中所列出的方法没有响应的实现,由其它类来实现。委托是指给一个对象提供机会对另一对象中的变化做出反应或者相应另一个对象的行为。其基本思想是协同解决问题。
从方法的定义我们不难看出委托模式能够起到两方面的作用:
第一:代理协助对象主体完成某项操作,将需要定制化的操作通过代理来自定义实现,达到和子类化对象主体同样的作用。
第二:事件监听,代理对象监听对象主体的某些重要事件,对事件做出具体响应或广播事件交给需要作出响应的对象。
使用步骤
委托工作:
1.1定义协议与方法
1.2声明委托变量
1.3设置代理
1.4通过委托变量调用委托方法
代理工作:
2.1遵循协议
2.2实现委托方法
协议在何处定义
如果一个类需要用代理来传值,那么协议可以写在.h文件中
要是多个类都要使用这个传递方法,可以新建一个类来写。
weak作用
通常,我们将delegate设置为weak属性,这样做的依据是什么呢?
代理传值发生在反向传值中,即B是A的属性(也叫做B是A的依赖),从B往A传值。
这时,A是持有B的,要想让A执行B遵循的协议方法,就要将A设置为B的代理。delegate持有了A,这样就构成了循环引用,如果将delegate设置为weak,它不再持有其他对象,也就不持有A,消除了引用环。