前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS优化_你可能没注意到的delegate

iOS优化_你可能没注意到的delegate

作者头像
Dwyane
发布2018-05-22 17:36:35
5150
发布2018-05-22 17:36:35
举报
文章被收录于专栏:技术总结技术总结

前言:

相信很多人都熟悉“委托模式”(delegate pattern),这个模式主要是为了数据与业务逻辑解耦,举个栗子: 我们的软件需要从后台服务器那边获取数据,而由于网络请求,不可能立即返回,而在获取数据的过程中阻塞应用,则会让用户崩溃,用户体验很差。这时,我们就可以使用委托模式,当然也可以用block,当获取完网络数据后,回调委托对象

流程:

定义一套接口,某个对象接受另一个对象的委托,则需遵从此接口,从而成为其“委托对象”,而”另一个对象“可以给其委托对象回传一些信息,也可以发生相关事件时通知委托对象。就像老板饿了,助理接受老板的吩咐,去kfc买牛肉汉堡,助理去到,打电话给老板说,牛肉汉堡没了,给老板买了鸡肉卷。这时,老板相当于”另一个对象“,助理相当于”某个对象“,,是老板的”委托对象“。

委托协议我们一般定”可选的“(optional),原因很简单,因为协议方法可以很多个,所以我们可以看到很多协议方法那里有@optional的关键字,像上面老板叫助理买kfc的栗子(协议名建议用驼峰命名法): 暂且定”另一个对象中“为”Boss类“,而定义”某个对象“即delegate为”assistant类“ <pre>Boss.h文件中 @protocol BugKFCDelegate @property (nonatomic, weak) id <BubKFCDelegate> delegate; @optional - (void)bugKFC:(KFC*)kfc didReceiveData:(NSData )data; - (void)bugKFC:(KFC)kfc didFailWithError:(NSError *)error; @end</pre>

好了,对委托的介绍不那么详细了,网上大把资料介绍基本用法,在这里我只介绍下重点,这也可能是大家并没有注意到的细节:

1、属性delegate需定义成weak,不可以是strong,两者之间必须为“非拥有关系“。委托对象(assistant类)会持有本对象(也就是上面例子的”Boss类“),而定义boss类的delegate属性,如果delegate是strong定义的,则会被boss类所拥有。这样就变成相互拥有了,造就著名的”保留环“,看下图:

所有权关系图

2、检测协议方法是否调用,以及是否要优化程序执行效率

在委托对象调用可选方法,我们在.m文件传数据过去:<code>[self.delegate bugKFC:self didReceiveData:data];</code>

注意:如果delegate对象中实现了<code>- (void)bugKFC:(KFC*)kfc didReceiveData:(NSData *)data</code>,那就很正常,一旦不实现该方法,又传了值过去,程序就会崩掉,所以我们应该加个判断 <pre>if ([_delegate respondsToSelector:@selector(bugKFC:self didReceiveData:)]) { [self.delegate bugKFC:self didReceiveData:data]; }</pre> 有了上面的判断,即使<code>delegate</code>对象没有实现委托协议的方法,也不会造成程序奔溃

但是,如果委托协议方法很多,那么很有可能类中会出现大量的<code>respondsToSelector</code>,你想下,这个判断是否响应方法的<code>selecotor</code>,除了首次判断有用外,后续的判断似乎有点多余,毕竟我们又不去改代码,代码不会自己变。为了优化程序效率,我们得用其他方法把是否响应某个协议方法这一信息缓存起来,我们可以用属性<code>Bool</code>值,当然可以用结构体<code>struct</code>会更高大上 先定义结构体先: <pre>//注意结构体的位置 struct { int BugKFCStateOK : 1; int BugKFCStateError : 1; int BugKFCStateUnknow : 1; } _BugKFCState;</pre>

定义结构体,放其在 <pre>@interface Boss (){ ...//结构体位置 @end</pre>

实现缓存功能的的代码,可以写在属性delegate的setter方法,只要delegate有调用,缓存功能的代码就会生效 <pre>

  • (void)setDelegate:(id<BugKFCDelegate>)delegate { _delegate = delegate; _BugKFCState.BugKFCStateOK = [_delegate respondsToSelector:@selector(returnName:)]; } </pre>

接着再判断委托对象是否响应某个协议方法,则可以写成 <pre> if (_BugKFCState.BugKFCStateOK) { NSLog(@"买到啦"); }</pre> 这个方法可以极大的改进执行速度,提高程序效率,朋友们可以一试。

总结:

1、定义delegate属性时,用weak修饰,不可用strong,以免造成”保留环“; 2、遇到<code>optional</code>的委托协议方法时,一定要用检测是否委托对象调用的该个协议方法,检测方法为<code>respondsToSelector</code>; 3、如果协议方法多次调用,那么最好优化下,此文用结构体缓存状态,不用每次调用<code>respondsToSelector</code>方法,极大提高程序执行效率

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.03.07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 流程:
  • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档