网易严选|iOS-代码细节优化三


网易严选|iOS-代码细节优化三
前面我们主要讲了Objective-C的一些代码优化细节 , 那么同为用作Apple开发的Swift也是有很多需要注意的细节 , 今天我们就来聊一聊 。
一:减少使用Any/AnyObject这是因为Any/AnyObject缺少明确的类型信息 , 编译器无法进行类型检查 , 进而就会带来一些问题 , 比如:
1.编译器无法检查类型是否正确保证类型安全 。
2.代码中大量的as?转换 。
3.类型的缺失导致编译器无法做一些潜在的编译优化 。
第一和第三条我们很好理解 , 那么第二条的as?会有什么问题呢?
当我们使用Any/AnyObject时会频繁使用as?进行类型转换 。 这在编译运行时看着好像没什么问题 , 因为并不会导致Crash 。 但代码错误至少应分为两类 , 一是程序本身的错误引发的Crash , 另一种是业务逻辑错误 。 而使用as?只是避免了程序错误Crash , 并不能防止业务逻辑错误 。 比如当dataString时才会进行处理 。 但是当String类型发生了改变 , 使用方并不知道已变更没有做相应的适配 , 这时候就会造成业务逻辑的错误 。 而这类错误一般更难发现 。
使用自定义类型代替Dictionary代码中使用大量Dictionary会降低代码的可维护性 , 也会带来潜在的bug , 比如:
【网易严选|iOS-代码细节优化三】1.key需要字符串硬编码 , 编译时无法检查 。
2.value没有类型限制 。 修改时类型无法限制 , 读取时需要重复类型转换和解包操作 。
3.无法利用空安全特性 , 指定某个属性必须有值 。
自定义类型还有个好处 , 例如JSON自定义类型时会进行类型/nil/属性名检查 , 可以避免将错误数据丢到下一层 。
而适合使用Dictionary的场景:数据不使用 - 数据并不读取只是用来传递和解耦 - (1.组件间通信解耦使用HashMap传递参数进行通信 。 2.跨技术栈边界的场景 , 混合栈间通信/前后端通信使用HashMap/JSON进行通信) 。
其他的一些细节1.使用枚举关联值代替Any 。
2.使用泛型/协议关联类型代替Any 。 使用泛型协议关联类型代替Any , 通过泛型类型约束来使编译器进行更多的类型检查 。
3.使用枚举/常量代替硬编码代码中存在重复的硬编码字符串/数字 , 在修改时可能会因为不同步引发bug 。 尽可能减少硬编码字符串/数字 , 使用枚举常量替代 。
4.使用KeyPath代替字符串硬编码 。 KeyPath包含属性名和类型信息 , 可以避免硬编码字符串 , 同时当属性名或类型改变时编译器会进行检查 。
二:内存安全
减少使用!属性

  1. 减少使用!进行强解包 。 因为会在读取时隐式强解包 , 当值不存在时产生运行时异常导致Crash 。
  2. 避免使用try!进行错误处理 。 因为会在方法抛出异常时产生运行时异常导致Crash 。
  3. 使用weak避免循环引用 。 减少使用unowned , unowned在值不存在时会产生运行时异常导致Crash , 只有在确定self一定会存在时才使用unowned
4.减少使用可选值 。 可选值的价值在于通过明确标识值可能会为nil并且编译器强制对值进行nil判断 。 但不应该随意定义可选值 , 可选值不能用let定义 , 并且使用时必须进行解包操作相对比较繁琐 。 在代码设计时应考虑这个值是否有可能为nil , 只在合适的场景使用可选值 。
5.使用init注入代替可选值属性 , 并避免随意给予可选值默认值 。
6.减少var属性 。 使用计算属性可以减少多个变量同步带来的潜在bug(计算属性因为每次都会重复计算 , 所以计算过程需要轻量避免带来性能问题) 。