用什么传?
delegate和block的选型
一、为什么要选型而不是开发各自选择?
1. 灵活性
为什么要限制灵活性?在任何时候开发都可以各显神通吗?
在架构思维上,限制灵活性的原因往往是想要换取可维护性。
当不同的技术充斥在代码中的时候,很容易造成难以阅读,难以接入的情况。封装一个组件最好限制只有一种和业务层交流的方式。
2. 代码影响范围
为什么要限制影响?不限制影响会怎么样。
以滥用单例和notification为例,如果不在场景上对这辆者进行限制,影响返回会很广。对notification的限制可以体现在代码规范上,比如在写notificaition的key时,需要统一写到constant文件中,这样在提交代码或者做代码评审的时候,就可以发现组内成员加了通知,然后可以讨论为什么加通知。
二、根据可读性选择
在不涉及架构和原则情况下,如果回调方法很复杂,建议使用delegate
可读性的评判标准在于阅读的复杂度,造成阅读复杂的原因主要是一个类包含多个回调方法,或者一个回调中含有多个参数。delegate相比较于block更方便管理多个回调事件和更复杂的回调参数;而block回调名称难以像一个方法一样起的这么长,回调参数如果太长也会难以阅读,或者需要注释才可以明白。
三、根据调试的难易程度选择
在单步调试时,delegate的可调式度更高,点击调用处就可以跳转到实现方法中。而点击block调用的地方,只会跳转难道属性列表,如果要找到实现代码,须到实现对象中搜索寻找。
delegate不适合频繁切换实现者,比如单例,而block在切换实现者上
可维护性:delegate更高,block需要避开循环引用,需要选择使用weakSelf还是strongSelf。
四、根据统一回调选择
统一回调:在一个类中,负责处理回调的地点是统一的。
统一回调的好处:所有的回调处理逻辑都在一处,更加容易寻找,对于回调方法,也是单一职责。
delegate更加适合实现统一回调,block总是会将实现的代码块散落在类的各地。
block能否实现统一回调:可以,在各处的block回调中调用一个私有方法就可以实现统一回调,但是有一个缺点,就是私有方法的名字是由实现者自己命名的,这样一来在不同的类中,这个统一方法名将不一样,开发的时候到不同类里去寻找统一回调点,还需要先找到block才行。而在架构的思维上,可以在回调方式的选择上规避掉这种缺点,如果使用离散型思路,delegate的方式,每个类的回调都是遵循协议的,这样在跨文件,跨模块阅读和修改代码上就有了快速接入的基础。
五、根据离散和集约型理论的选型
当回调之后要做的任务在每次回调时都是一致的情况下,选择delegate,在回调之后要做的任务在每次回调时无法保证一致,选择block。
集约型:集约型的设计模式在很多时候被用到,如AFNetworking,核心的原理是多目的,多个不同的方法集约在一个类中,或者通过改变参数调用一个方法实现多种功能,那么可以说这个类和这个方法都是集约的。
离散型:离散型的设计模式如CTNetworking,核心的价值观是,被离散的方法和类,都是单一目的的,而对于一个单一目的的类或者方法,回调的任务也是相同的。
六、根据性能选择
放在最后面就代表着最不重要。
在绝大多数情况下的delegate和block选型上完全可以不用考虑这一点性能,丝毫没有意义。
从实现原理上来看,block会让代码块中的变量引用计数加1,而delegate只是一个引用。
NSNotification怎么用
NSNotification是以广播的方式传递消息的类型。
一、最合适的使用场景
跨层访问的场景最适合用notification,在代码中,我们一般会避免跨层访问,但有时业务需求要求我们这么做,比如网络环境的切换通知等信号类型切换时。
二、如何控制影响范围
将Key都封装成全局变量写到Constants文件中,避免文本式的写notification的key,在codereview中探讨为何如此使用。
传什么?
Dictionary 和 Model的选型
一、根据可读性选择
在单步调试的阶段,Dictionary的可读性很高,LLDB中可以直接把Dictionary的数据结构打印出来。但是Model只能打出内存地址。
在使用上,Model能更清楚的表示类型以及结构,通过点语法就可以调用相应的字段。而Dictionary的类型是模糊的,在代码阶段,数据结构除了注释无法查看。在正常使用时,取出Value需要一个String类型的Key,这对于使用这来说,需要copy一下string的内容。
字典的Key能否可视化? 可以,但是还是没有Model易用,需要写比较长的代码来解决。首先就是须针对Dictionary中的key写全局变量,然后在一个.h文件中extern这些key的变量。一个类要取出字典value时可以引用.h文件,取出key。
二、根据效率选择
Dictionary之间的转换效率很高,从服务端拿到Dictionary的时候,转换成一个充分必要的Dictionary与转换成一个充分必要Model来比要高效的多。尤其是Model中的属性存在Array时,需要遍历转换subModel,成本太高。
三、根据维护成本
在服务端数据标准化差的时候,容易创建很多个Model用于不同的场景,类型爆炸,提升了维护成本。
怎么传?
一、标准数据传递会有的问题
现在有个假设,一个不靠谱的服务端,给客户端提供了一个接口,可以用于5个view的展示。
-
解析数据的代码散落在各处 拿到数据->解析数据->传递到view->二次解析->展示到view,有没有发现?数据解析的操作将会分散在各处:vc中、view中、model中。难以管理。
-
VC和数据处理没有隔离
二、使用Reformer(改良者)
image.png-
Reformer在实际使用中是一个文件,以view的名字开头reformer结尾。
-
由于reformer和view一一对应,所以从response到足以展示view的数据只需要转换一步。
-
由于数据转换的过程都是在reformer中,对于vc来说只需要关注数据传递。
网友评论