关于self.delegate=self的思考

作者: flightlessBirdT | 来源:发表于2017-11-17 12:16 被阅读233次

关于代理模式的使用,我们都很熟悉。代理的使用场景是为了解决一对一的消息传递。比如A想执行方法M 但是A不方便执行。这时我们可以将B设置为A的代理 让B去执行。代理模式在日常开发中被大量使用,这里不再去赘述。今天我想说说的是self.delegate = self ,即自身代理的问题。

什么叫自身代理

我给大家举个最简单的例子:
当我们自定义了一个UITableView。我们可以将其的代理和数据源设置为自己。

#import "TestTableView.h"

@interface TestTableView ()<UITableViewDelegate>

@end

@implementation TestTableView

-(instancetype)initWithFrame:(CGRect)frame{
   if (self = [super initWithFrame:frame]) {
      self.delegate = self;
   }
  return self;
}

#pragma mark UITableViewDelegate
(这里实现代理方法)........

@end

这样是不是比较好理解?但其实自身代理有更为复杂的应用场景。我结合一下自己项目里的业务需求讲述一下。

我们简化一下需求:比如一个企业管理软件。有个需求是展示企业组织架构。有一个控制器A。A里面是部门列表(销售部,市场部,人事部,技术部等等)。每个部门点击去是当前部门的子部门列表(比如技术部点进去 可以有运维组 前端组 后端组等等),子部门列表中的每个部门点进去也是当前子部门的子部门列表(比如前端组点进去 可以有web段 移动端等等),以此类推 一直循环下去。

拿到这个需求我们怎么构思代码?

显而易见,不可能每个层级的部门列表都写一个页面或者控制器去展示。假如有家大公司部门层级很深,你总不可能一个个页面去对应的写一套代码吧。所以不管它是几级部门,我们都可以用一个类去描述(这里假设是Class A)。我们用A初始化一个对象,比如一级部门A0,从A0中任意点击一个部门,进入其子部门(即二级部门),我们需要再创建一个A的对象A00, 然后从A0跳转到A00。此时A0A00的内存虽然不同,但其储存的代码是一模一样的。从二级部门进入三级部门同样的道理。

这个需求的数据展示很简单。那么我们再来加一个简单的需求,如果希望在每一级部门的页面都可以进行其父部门的操作呢?比如在A0的子部门列表中有个按钮可以删除A0部门。看到这里你们可能有点晕 这里我用钉钉的组织架构功能举个例子。

从公司主页点进去是一级部门列表
屏幕快照 2018-07-12 上午11.11.32.png
从市场销售部点进去,是二级部门列表
屏幕快照 2018-07-12 上午11.11.44.png

点击右上角的更多我们可以操作市场销售部的属性,比如删除市场销售部,或者重命名市场销售部。

那这个需求又如何去构思代码?
这时候我们就需要消息传递了。

我的做法是在A0跳转到A00的时候将A00的代理设置为A0,因为A00A0都是用A去描述的,所以我们可以用 self.delegate = self

这是我项目中的代码(因为实际业务需求比我举的例子要复杂的多,所以这里代码比较繁琐)申明一个类 OrganizationalStructureController 用来描述每一级部门列表,在 OrganizationalStructureController 中做层级跳转的时候再创建一个 OrganizationalStructureController 的对象,把需要的数据传递过去,并设置其代理为本身。这里的vc好比是A00,self是A0vc.delegate=self 即设置A00的代理为A0

屏幕快照 2018-07-12 上午11.12.06.png

这是OrganizationalStructureController的代理方法

屏幕快照 2018-07-12 上午11.12.19.png

当我们从A00界面点击删除的时候,A00的代码会执行 makeSureDeleteDepartment 的方法,而A00的代理是A0(我们在A0 跳转到 A00的方法中已经设置了)。所以当删除方法执行的时候,A0会执行 deleteIndexpath: 的方法(这里有点绕 注意不是A00执行 虽然该代码同样存在于A00上 但是走的却是A0的代码)。 deleteIndexpath: 方法里的self其实是A0,也就是走的是A0的数据源更新。

屏幕快照 2018-07-12 上午11.12.30.png

看到这里,可能有的人会想为什么要这么麻烦,直接在 OrganizationalStructureControllerviewWillApper 的方法里去请求最新的数据进行渲染不就行了。但实际上需求不仅仅是删除这么简单的操作,这里只是举个例子,引入自身代理的这种思想。

相关文章

网友评论

    本文标题:关于self.delegate=self的思考

    本文链接:https://www.haomeiwen.com/subject/sogdvxtx.html