Swift中17条最佳实践规范_第1页
Swift中17条最佳实践规范_第2页
Swift中17条最佳实践规范_第3页
Swift中17条最佳实践规范_第4页
Swift中17条最佳实践规范_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

这篇文章讲述的范围主要针对 Swift 语言以及 Swift 标准库 即便如此 如 果能提出一个独特的 Swift 的视角和见解 我们依然会提供诸如 Swift 在 Mac OS iOS WatchOS 以及 TV OS 上使用的特别建议 而如何在 Xcode 和 LLDB 上 有效地使用 Swift 这样的建议也会以 Hints tips 的风格提供 这是工作时的一系列笔记整理出来的 文中大多数建议是经过深思熟虑的 但 仍可以有其他类似的解决方法 这个最佳实践不是强加或者推荐 Swift 在程序 面向对象或者函数风格上的 应用 更重要的是 这里要讲述的是务实的方法 如有需要的话 某些建议可能会 集中在面向对象或者实用的解决方法 这个过程需要付出很多的努力 非常感谢为本文做出贡献的那些人 此外 可以在 Swift Lang slack 里面讨论 请先确保所有的示例是可以运行的 某些示例可能不是正确 这个 markdown 能够转换成一个 Mac OS X playground 1 一般来说 Apple 都是正确的 遵循 Apple 喜欢的或者示范的处理方式 在任何情况下 你都应该遵循 Apple 的代码风格 正如他们 The Swift Programming Language 这本书里面的定义一样 然而 Apple 是个大公司 我们 将会看到很多在示例代码中的差异 2 永远不要仅仅为了减少代码量而去写代码 尽量依赖 Xcode 中的自动补全 代码 自动建议 复制和粘贴 详尽的代码描述风格对其他代码维护者来说是非常 有好处的 即便如此 过度的冗余也会失去 Swift 的重要特性 类型推断 1 命名 正如 Swift Programming Language 中的类型名称都是以大驼峰命名法命名的 例如 VehicleController 变量和常量则以小驼峰命名法命名 例如 vehicleName 你应该使用 Swift 模板去命名你的代码而不是使用 Objective C 类前缀的风 格 除非和 Objective C 接连 不要使用任何匈牙利标识法 Hungarian notation 命名 例如 k 为常量 m 为方法 应使用简短的命名并且使用 Xcode 的类型 Quick Help 01 png click 去查明变量的类型 同样地 不要使用小写字母 下划线 SNAKE CASE 的命名方式 唯一比较特别的是 enum 值的命名 这里需要使用大驼峰命名法 这个也是遵 循 Apple 的 Swift Programming Language 风格 1 2 3 enum Planet case Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune 在所有可能的情况里 名称的不必要减少和缩写都应该避免 将来你应该能在 没有任何损害和依赖 Xcode 的自动补全功能的情况下 确切地指出类型特征 ViewController 非常普遍的缩写如 URL 是允许的 缩写应该用所有字母大写 URL 或者所有字母小写 url 表示 对类型和变量使用相同的规则 如果 url 是个类型 则应该为大写 如果是个变量 则应该为小写 2 注释 注释不应该用来使代码无效 注释代码会使代码无效且影响代码的整洁 如果 你想要移除代码 但是仍想保留以防代码在以后会用到 你应该依赖 git 或者 bug tracker 3 类型推断 在可能的地方 使用 Swift 的类型推断以减少多余的类型信息 例如 正确的 写法 1 var currentLocation Location 而不是 1 var currentLocation Location Location 4 Self 推断 让编译器在所有允许的地方推断 self 在 init 中设置参数以及 non escaping closures 中应该显性地使用 self 例如 1 2 3 4 5 6 7 struct Example let name String init name String self name name 5 参数列表类型推断 在一个闭包表达式 closure expression 中指定参数类型可能导致代码更 加冗长 只有当需要指定类型时 1 2 3 4 5 6 7 8 9 10 let people Mary 42 Susan 27 Charlie 18 let strings people map name String age Int String in return name is age years old 如果编译器能够推断类型 则应该去掉类型定义 1 2 3 4 let strings people map name age in return name is age years old 使用排序好的参数编号命名 0 1 2 能更好地减少冗余 这经常能 够完整匹配参数列表 只有当 closure 的参数名称中没有过多的信息时 使用编号 命名 例如特别简单的 maps 和 filters Apple 能够并将会改变由 Objective C frameworks 转换过来的 Swift 的参 数类型 例如 选项被移除或者变为自动展开等 我们应有意地指定你的选项并依 赖 Swift 去推断类型 减少在这种情况下程序中断的风险 你总是应该有节制地指定返回类型 例如 这个参数列表明显过分冗余 1 2 3 4 dispatch async queue Void in print Fired 6 常量 在类型定义的时候 常量应该在类型里声明为 static 例如 1 2 3 4 5 6 7 8 9 10 11 12 struct PhysicsModel static var speedOfLightInAVacuum 299 792 458 class Spaceship static let topSpeed PhysicsModel speedOfLightInAVacuum var speed Double func fullSpeedAhead speed Spaceship topSpeed 使用 static 修饰常量可以允许他们在被引用的时候不需要实例化类型 除了单例以外 应尽量避免生成全局常量 7 计算型类型属性 Computed Properties 当你只需要继承 getter 方法时 返回简单的 Computed 属性即可 例如 应 该这样做 1 2 3 4 5 class Example var age UInt32 return arc4random 而不是 1 2 3 4 5 6 7 class Example var age UInt32 get return arc4random 如果你在属性中添加了 set 或者 didSet 那么你应该显示地提供 get 方法 1 2 3 4 5 6 7 8 9 10 class Person var age Int get return Int arc4random set print That s not your age 8 实例转换 Converting Instances 当创建代码去从一个类型转换到另外的 init 方法 extension NSColor convenience init mood Mood super init color NSColor blueColor 在 Swift 标准库中 对于把一个类型的实例转换为另外一种 现在看来 init 方法是比较喜欢用的一种方式 to 方法是另外一种比较合理的技术 尽管你应该遵循 Apple 的引导去使用 init 方法 1 2 3 4 5 struct Mood func toColor NSColor return NSColor blueColor 而你可能试图去使用一个 getter 例如 1 2 3 4 5 struct Mood var color NSColor return NSColor blueColor getters 通常由于应该返回可接受类型的组件而受到限制 例如 返回了 Circle 的实例是非常适合使用 getter 的 但是转换一个 Circle 为 CGPath 最 好在 CGPath 上使用 to 函数或者 init 扩展 9 单例 Singletons 在 Swift 中单例是很简单的 1 2 3 class ControversyManager static let sharedInstance ControversyManager Swift 的 runtime 会保证单例的创建并且采用线程安全的方式访问 单例通常只需要访问 sharedInstance 的静态属性 除非你有不得已的原因去 重命名它 注意 不要用静态函数或者全局函数去访问你的单例 因为在 Swift 中单例太简单了 并且持续的命名已经耗费了你太多的时间 你应该有更多的时间去抱怨为什么单例是一个反模式的设计 但是避免花费太多时 间 你的同伴会感谢你的 10 使用扩展来组织代码 扩展应该被用于组织代码 一个实例的次要方法和属性应该移动到扩展中 注意 现在并不是所有的属性 类型都支持移动到扩展中 为了做到最好 你应该在这个限制中使用扩展 你应该使用扩展去帮助组织你的实例定义 一个比较好的例子是 一个 view controller 继承了 table view data source 和 delegate protocols 为了使 table view 中的代码最小化 把 data source 和 delegate 方法整合到扩展中以 适应相应的 protocol 在一个单一的源文件中 在你觉得能够最好地组织代码的时候 把一些定义加 入到扩展中 不要担心把 main class 的方法或者 struct 中指向方法和属性定义 的方法加入扩展 只要所有文件都包涵在一个 Swift 文件中 那就是没问题的 反之 main 的实例定义不应该指向定义在超出 main Swift 文件范围的扩展 的元素 11 链式 Setters 对于简单的 setters 属性 不要使用链式 setters 方法当做便利的替代方法 正确的做法 1 2 instance foo 42 instance bar xyzzy 错误的做法 1 instance setFoo 42 setBar xyzzy 相较于链式 setters 传统的 setters 更为简单和不需要过多的公式化 12 错误处理 Swift 2 0 的 do try catch 机制非常棒 13 避免使用 try 一般来说 使用如下写法 1 2 3 4 5 6 do try somethingThatMightThrow catch fatalError Something bad happened 而不是 1 try somethingThatMightThrow 即使这种形式特别冗长 但是它提供了 context 让其他开发者可以检查这个代 码 在更详尽的错误处理策略出来之前 如果把 try 当做一个临时的错误处理是 没问题的 但是建议你最好周期性地检查你代码 找出其中任何有可能逃出你代码 检查的非法 try 14 避免使用 try try 是用来 压制 错误 而且只有当你确信对错误的生成不关心时 try 才 是有用的 一般来说 你应该捕获错误并至少打印出错误 15 过早返回 Guards 可能的话 使用 guard 声明去处理过早的返回或者其他退出的情况 例如 fatal errors 或者 thorwn errors 正确的写法 1 2 3 4 guard let safeValue criticalValue else fatalError criticalValue cannot be nil here someNecessaryOperation safeValue 错误的写法 1 2 3 4 5 if let safeValue criticalValue someNecessaryOperation safeValue else fatalError criticalValue cannot be nil here 或者 1 2 3 4 if criticalValue nil fatalError criticalValue cannot be nil here someNecessaryOperation criticalValue 这个 flatten code 以其他方式进入一个 if let 代码块 并且在靠近相关的 环境中过早地退出了 而不是进入 else 代码块 甚至当你没有捕获一个值 guard let 这个模式在编译期间也会强制过早退 出 在第二个 if 的例子里 尽管代码 flattend 得像 guard 一样 但是一个毁灭性 的错误或者其他返回一些无法退出的进程 或者基于确切实例的非法态 将会导致 crash 一个过早的退出发生时 guard 声明将会及时发现错误 并将其从 else block 中移除 16 Early 访问控制 即使你的代码没有分离成独立的模块 你也应该经常考虑访问控制 把一个定 义标记为 private 或者 internal 对于代码来说相当于一个轻量级的文档 每一 个阅读代码的人都会知道这个元素是不能 触碰 的 反之 把一个定义为 public 就相当于邀请其他

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论