源码阅读中的收获

最近在做短视频相关的模块,于是在看 GPUImage 的源码。其实有一定了解的伙伴一定知道 GPUImage 是通过 addTarget 链条的形式添加每一个环节。在对于这样的设计赞叹之余,想到了实际开发场景下可以用到的场景,借此分享。

我们的项目中应该有很多的聚合页,每个聚合页上都有 feed 流,而在很多的项目中 feed 流的场景都是可以进行复用的。而在这样的场景下我们希望复用的 feed 流中的 cell 可以在多个界面上进行复用。但是如果每一个 cell 上又有几个点击事件,如果每一个 Controller 上都有一堆的事件处理代码,又会代码冗余量巨大。

开发中遇到的痛点

随便举个例子,微博的信息流,微博很多业务都是这样的界面进行展示,如果每个 cell 的点击事件代理回 controller 中进行执行,那 controller 有多重可想而知... 而且一旦以后业务调整,某些跳转页面更改,波及的页面之广,也是无法接受的。

WechatIMG67.jpeg

这个时候就会想可不可以在一个地方固定的处理这些事件?

一些解决方案

我记得对于这个问题, 源神 曾经提出过 self-manager 的概念可以解决类似的问题。在源神的解决方案中,feed 按钮的功能相对单一这样的方式是一种较好的方案,但是 feed 上的按钮根据业务场景做不一样的跳转,这样的处理又该如何处理呢? 其实对于源神的方案其实传入枚举,对它做对应的处理就可以了。

还是用微博进行举例,现在我们有A,B,C三条业务线都会对会有 feed 展示这个 cell。

  • A 业务线要求就是要求底部 tabbar 是转发,评论和点赞的功能
  • B 业务线的要求是转发的按钮是跳转到业务线 A, 评论按钮的点击事件跳转到业务线C,点赞按钮的功能保留
  • C 业务线的要求是转发的按钮跳转到业务线 B, 评论的按钮保留原功能,点赞的按钮跳转到业务线 B 这样的操作。

对于这样的恶心要求(不要觉得我天马行空,我真的遇到过这类似的业务场景,而且也确实有对应的需要),如果此时还是使用 self-manager,来对状态进行判断。可能伪代码的结构大致如下。

typedef NS_ENUM(NSInteger,BusinessLineType){
    BusinessLineTypeA = 0,
    BusinessLineTypeB,
    BusinessLineTypeC,
}

typedef NS_ENUM(NSInteger,CommentBtnHandleType){
    CommentHandleTypeA = 0,
    CommentHandleTypeB,
    CommentHandleTypeC,
}

......

-(viod)configureCellWithBusiness:(BusinessLineType)businessType{


//根据 businseeType 进行判断 将评论点击事件的枚举传入下一级 然后正确响应点击事件

//根据 businseeType 进行判断 将转发按钮事件根据业务线枚举讲点击枚举传入下一级

...

}

不知道大家对于这样的代码看到后的感受是怎么样的,但是我可以设想到,在没有足够的文档说明的情况下,如果组里来了一个新的小伙伴或者让一个对当前业务场景不足够熟悉的小伙伴进行维护,一定很抓狂,感觉这样的形式在维护上的成本还是比较高的。所以这样的方案还是比较适合处理业务上职责比较单一的小块。

此外对于大厂可能有一条业务线的业务代码需要使用到多个产品中的情况,这样的方案一样也就不再适用了。因为 view 层承接了业务。 而两个产品的设计并不相同,但是业务的逻辑是相同的,这个时候就不是简单的替换 view 层就能完成功能添加那么简单的问题了。

曾经的方案

基于上边的复杂业务可读性差和让业务和 view 完全解耦的思路,这个时候就需要思考,是不是有更好的处理方案。在一开始我们的项目出现这样的需求的时候,我想到的解决方案是创建一个事件处理中心的概念。

就是将 cell 中的每一个试图需要响应事件回调到 cell 层,然后 cell 中有一个 delegate , 创建一个叫 HandleEventCenter 的对象(controller 创建数组维护)来起到回调中心的作用。

这样对于上边的需求,我们的处理方案就会变得更加灵活,可以写一个通用处理一般场景下的基类,然后根据业务线的不同继承自基类,重写需要特殊处理的基类的问题。

这是看下这样处理的优缺点:

  • 解决了 view 层和业务代码之间代码耦合的问题,同时事件的处理不需要在每个 controller 上写多次。同时可以较好的应对点击事件在不同业务线处理不同逻辑的问题,而且代码的可读性问题也得到了解决。

  • 问题就在源神提到的我们要将事件一层层向上回调,写了很多坨看上去很不爽的回调代码的问题(无论 delegate 还是 block 都不够优雅)

更好的处理方案

看到 GPUImage 的源码之后,我当时想到的方式,就是用这种事件链条的形式,将事件传递下去就行了。其实在日常开发中,我们都习惯了使用 delegate 或者 block 两种方式对事件向上进行传递,但是忘记了系统很常用的的 target - action 模式。

下边来看下我们曾经固有模式和现在解决方案的区别。

  • 曾经的方案:我们捕捉到事件执行 -> 传给上一层(block 或者 代理的模式) -> 再上一层 -> 最后的代理中心 -> 事件响应

  • 现在的解决方案:将事件代理中心 -> 传递给 cell 层 -> 传递给各个事件层 -> 在事件执行处调用处理中心对应的方法

这样每层一大堆恶心代码问题得到了解决,也完全抽离了试图和业务之间的耦合性。除此之外,如果我们的 cell 上添加了新的响应事件,不需要在层层响应,只需要在处理中心添加新的代理,然后再执行处 target 调用对应方法即可。感觉很大程度上减少了代码量,同时降低了维护成本。

一些题外话

其实我们在实际的开发中,发现一些特殊的场景下,事件处理中心的方案存在很大的弊端。比如 我们的界面上有一个编辑功能的按钮,按钮点击后,我们会跳转到一个新的界面对 cell 的数据源进行修改,这个时候再返回,我们需要根据新的数据源刷新当前的 cell 。 事件处理中心的处理方案,就不足以解决这样复杂的问题,否则就需要和 tableView 产生耦合。当然这样的问题,我们取巧的进行了解决,本文就不进行介绍了。

提这样的题外话,不过是想表达每一种方案中可能或多或少的都存在各种各样的问题,但是针对问题,我们总是可以找到更好的解决方案。总是思考着,我们的程序也终究会变得更好。

当然本文中提到的方案也可能存在各种各样的问题,希望不吝赐教,希望在探讨中找到更平衡的方案。共同进步~~~

最后

之前看源码,一直关注点都在于技术的细节和如何解决问题上。但是经此发现,在读源码的过程中,真的可以思考那些优秀的开源的代码,为什么这样设计,在我们日常开发中,这样的设计是不是可以得到推广和应用。我相信在这一过程中,不知不觉,大家都会获得足够的成长和收获~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 2017.02.22 可以练习,每当这个时候,脑袋就犯困,我这脑袋真是神奇呀,一说让你做事情,你就犯困,你可不要太...
    Carden阅读 1,321评论 0 1
  • 风之壹把刀阅读 226评论 3 5
  • 时隔差一礼拜 整整一年 见过几次面 每一次的最后一次 都近在心里 怕清楚却又很清楚 我们都很清楚 对不对 人生就是...
    maybegirl阅读 115评论 0 0
  • -1- 终于到了,已是凌晨。机场外漆黑,只有零星的路灯和出租车探照灯。我三步并作两步快速前行,衣袂在身后飘扬,拖着...
    七尾青阅读 431评论 0 0