委托和代理的相关概念


委托代理(degegate),顾名思义,把某个对象要做的事情委托给别的对象去做。那么别的对象就是这个对象的代理,代替它来打理要做的事。反映到程序中,首先要明确一个对象的委托方是哪个对象,委托所做的内容是什么。

委托机制是一种设计模式,在很多语言中都用到的,这只是个通用的思想

 

协议(protocol) 相当于 java 里的接口,delagate 就是接口的实现类(C中的回调类似);

数据源(datasource)就是对象遵循了存储数据的协议,可以存储使用数据

协议表示了方法可以被任何类所实现。

协议本身不是类。他们只是简单定义了一个其他对象可以实现的接口。当你的类实现了协议中的某个方法的时候也就是说你的类实现了那个协议。

 

委托与协议的关系:

大家应该都明白的是委托是协议的一种,顾名思义,就是委托他人帮自己去做什么事。也就是当自己做什么事情不方便的时候,就可以建立一个委托,这样就可以委托他人帮自己去实现什么方法。

 

作用:

传值 ;传事件。

1.所谓传值经常用在b类要把自己的一个数据或者对象传给a类,让a类去展示或者处理。(切分紧耦合,和代码分块的时候经常用)

2.所谓传事件就是a类发生了什么事,把这件事告诉关注自己的人,也就是委托的对象,由委托的对象去考虑发生这个事件后应该做出什么反映。(这个经常见,例如在异步请求中,界面事件触发数据层改变等等)

3.利用委托赋值,这种方法感觉是为了不暴露自己的属性就可以给自己复值,而且这样更方便了类的管理,只有在你想要让别人给你赋值的时候才调用,这样的赋值更可控一些。(例如tableView中的委托(dateSource)中常见)。

 

使用委托的步骤:

1. 创建一个协议

2. 添加一个委托属性到委托者(普通对象)的公共interface

3. 在委托者的实现中使用此委托属性

4. 在委托(委托对象即代理者)的实现的某个地方设置此委托代理属性

5. 在委托中实现协议方法(include<> on @interface)

步骤1、2、3可在委托者里实现,步骤4、5在委托中实现(通常是某个ViewController原因作为委托)

这里涉及到两个对象(委托者、委托),一个是普通对象,一个是委托对象(即代理者)。不要被它们的名字搞混。普通对象负责定义一个协议和一个属性,委托对象负责响应普通对象的委托,因此委托对象要实现此协议,且在其自身实现的某个地方设置此委托属性指向为自己。



注意事项:

1.delegate的命名要准确,尽量看名字就知道用法。

2.delegate和通知有的用法有些像,但是前者是单对单的,后者是单对多的情况。

3.在dealloc要把delegate至为nil

4.还有就是delegate设置属性的时候要用assign,不要用retain。

 

为什么我们不用retain而要用assign呢? 
原因就是在于iOS的reference counting的环境中,我们必须解决circular count的问题。 
让我们来写写我们平常都怎么用delegate的,下面的code我想大家应该不陌生 
- (void)someAction 

   myClass = [MyClass new]; 
   myClass.delegate = self; 
   .... 

这边很快就出现circular reference了 


假设上面的code是写在一个myViewController的物件当中, 
之后一旦myViewController的reference count变成1的时候,

 
myViewController跟myClass这两个兄弟两只剩下互相retain,那就变成了孤岛,没有持有方了,也​​就因此造成了memory leak!!! 

 

也因为这样,iOS官方文件才会要建议我们所以的delegate都要用assign property。 
也就是所谓"weak reference"(弱引用)的property,他的特色就是虽然会持有对方的reference(引用),但是不会增加retain count。 
如此下来,当myViewController的retain count变成0的时候,便可dealloc,否则在delalloc中会报错。 
同时在dealloc中,myViewController被release,同时myClass也跟着被release。 
- (void)dealloc 

   [myClass release]; 
   [super dealloc]; 

图示:

 

 事情就结束了吗? 没有!
这边还有一个大家常常忘记的重点,那就是上面的dealloc这样写会有潜在危险。 
应该要改成这样 
- (void)dealloc 

   myClass.delegate = nil; 
   [myClass release]; 
   [super dealloc]; 

你可能会很纳闷,myClass不是马上就会被release了吗? 干嘛还要先把他的delegate设成nil? 多此一举
那是在我们假设myClass会马上会被dealloc情况下,但是现实状况这个是不一定的
例如:有可能里面内部创建了个NSURLConnection对象(也就是有其他的操作),或许某些操作需要retain myClass。 
myClass没有马上dealloc,但是已经[super dealloc]了,那他的myClass.delegate不就正指向一个不合法的位置了吗? (此种pointer称作dangling pointer) 

 

解决方法是在MyViewController的dealloc中,在release myClass之前, 
要先把原本指向自己的delegate改设成nil,这样才可以避免crash发生。 
在我之前写的project,很大一部份的crash都是这样造成的,因为这个问题通常不是每次都发生, 
但是发生的时候确很难在重新复制,所以不可不慎啊。 

 

但是很兴奋的是到了iOS5中的Automatic Reference Counting 这个问题可以有所改善。 
在ARC中提出了一个新的weak reference的概念来取代原本的assign, 
weak reference指到的物件若是已经因retain count归零而dealloc了,则此weak reference也自动设成nil。 
而原本​​旧的这种assign的作法,在ARC中叫做__unsafe_unretained,这只是为了相容iOS4以下的版本

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值