# 老司机 iOS 周报 #63 | 2019-04-15

![ios-weekly](https://github.com/SwiftOldDriver/iOS-Weekly/blob/master/assets/ios-weekly.png?raw=true)
老司机 iOS 周报，只为你呈现有价值的信息。

你也可以为这个项目出一份力，如果发现有价值的信息、文章、工具等可以到 [Issues](https://github.com/SwiftOldDriver/iOS-Weekly/issues) 里提给我们，我们会尽快处理。记得写上推荐的理由哦。有建议和意见也欢迎到 [Issues](https://github.com/SwiftOldDriver/iOS-Weekly/issues) 提出。

## 新闻

### 🌟 [T 沙龙 - 互联网寒冬来袭，移动开发者如何破局](https://www.bagevent.com/event/2546122)

2019 年上海第一次 T 沙龙将于 4 月 20 日下午 1 点 30 分在上海虹口区天水路 172 号金融街海伦中心 B 座准时举办，此次活动邀请到了来自饿了么、iTutorGroup、极光、以及看雪论坛的业界资深从业者为大家分享他们在移动端技术深度和广度上的实践和思考。希望这次活动能对互联网寒冬下迷茫的移动开发者有一些启发，并成功破局！猛戳上方链接免费报名。

### [SwiftNIO 2.0 released](https://forums.swift.org/t/swiftnio-2/22136)

[@四娘](https://kemchenj.github.io/)：伴随着 Swift 5 的发布，SwiftNIO 也正式发布了 2.0 版本，这个版本主要有两个大更新：

1. 内置了 BoringSSL 作为 Vendor，不再依赖系统的 OpenSSL
2. 使用纯 Swift 实现了 HTTP2 协议，不再依赖于 nghttp2

### [Smoke Framework 1.0 released](https://forums.swift.org/t/smoke-framework-1/22710)

[@享耳先森](https://github.com/iblacksun)：Amazon 之前开源的 Swift Web Framework 发布 1.0 了，围绕着 AWS 的服务做了很多深度集成。1.0 使用 Swift 4.2, SwiftNIO 1.x 开发，即将发布 Swift 5 及 SwiftNIO 2 的版本，包含 `SmokeHTTP`,`SmokeAWS`, `SmokeDynamoDB`, `SmokeAWSCredentials` 几个子模块。

## 新手推荐

### 🌟 🐕 [纯 Swift 项目 - Xib | Storyboard 多人协作技巧](https://juejin.im/post/5c468f676fb9a049ed313183)

[@looping](https://github.com/looping)：本文就针对大家在使用 Storyboard 后出现的一些问题或质疑，提出了自己的看法，并列举了相关实践和建议，从而说明 Storyboard 和 Xib 虽然存在一些缺点，但也是值得学习研究的：

- 通过定制规范，合理的任务分工，以及有节制的使用工具来避免多人协作的坑 —— 对 Storyboard 的滥用（作者在文章中也给出了他们团队使用 Storyboard 的规范）；
- 通过良好的模块设计，熟练使用 Storyboard 分离代码的几个方案来避免由于 Storyboard 造成 ViewController 代码臃肿的问题；
- 需要修改类名或者变量名，应该善用 Xcode 的重构功能，来避免由于手动修改代码出现遗漏，导致应用崩溃等现象排查定位困难的问题；
- 经过测试，Storyboard 和 Xib 的执行效率并没有想象中的那么低，在重复创建实例时效率反而会比纯代码要高；
- 使用 Storyboard 和 Xib 进行布局，缺少约束或者约束冲突就会直接提示错误，适配不同设备也可以直接在 Interface Builder 上切换测试，效率和准确性比手写适配代码要高很多。

## 文章

### 🌟 [iOS app 秒开 H5 优化总结](https://juejin.im/post/5c9c664ff265da611624764d)

[@折腾范儿_味精](http://weibo.com/agvicking)：为了让 app 里面的 H5 页面实现秒开的效果，很多项目都采用了加载本地 H5 离线包的方式。如何实现这样的秒开就得分别从两个方面着手实现。

- 离线包的分发与下载
- WebView 的本地加载

需要补充一点的是，本文在 WebView 本地加载上都是以拦截的思路进行本地加载，UIWebView  自然可以顺畅使用 NSURLProtocol 但是在 WKWebView 里就面临很大的阻碍，而作者给出的代替方案还是 WKURLSchemeHandler 拦截，但面临的代价也是本来前端无感的拦截方案现在被迫前端也得受影响，打包的时候对资源协议头进行适配，这一点和很多公司的离线包方案略有差异。

在 WKWebView 里，即便是使用 WKURLSchemeHandler，资源拦截的方式也面临着与安卓差异化严重，对前端侵入性严重等问题，很多公司的离线包方案选择了另外的一条路，App 起本地服务器 run 前端离线包页面，做到让 WebView 无感知当前是一个“离线”页面，这样做能够最大程度的让前端对于离线包“无感”，也能忽略掉拦截 API 的平台差异导致的框架实现差异。

关于起本地服务器的这套方案，可以参考 [基于 LocalWebServer 实现 WKWebView 离线资源加载](https://www.jianshu.com/p/a69e77bf680c) 一文。它介绍了基于 Local Web Server 的方案来实现离线本地 H5 页面秒开。对这个方案有兴趣的朋友可以详细地看一下本篇文章给大家介绍的几套 Local Web Server 的开源方案并且文章还配有 Demo 代码可以参考。本文还向大家详细介绍了一下证书签名等部署本地服务会面临的问题。

### 🌟 🐢 [Building a dynamic modular iOS architecture](https://medium.com/fluxom/building-a-dynamic-modular-ios-architecture-1b87dc31278b)

[@莲叔](https://weibo.com/aaaron7/)：在以往讲述 iOS 架构/设计模式的文章中，往往 focus 在某个功能模块如何设计，如：MVC，MVP，VIPER，MVVM 等，讲述整个工程的设计模式和组织方法的讨论并不多见。本文从整个工程的架构着手，提出了一种工程的分层的架构方式，并且通过针对不同的层选择动、静态库来承载，实现了易于拓展、可组合、低耦合的工程架构，同时能兼顾编译时间和启动时间。针对各种不同粒度的需求变更，feature 级或者流程级都能够很好地兼容，文章还给出了对初学者很友好的 example app 来描述其思想，避免了读者在工程配置上可能花费的探索时间（毕竟要配置一堆动静态库的依赖关系还是有点蛋疼的)。值得阅读。

### 🌟 🐢 [百度 App 网络深度优化系列（一）：DNS 优化](https://www.infoq.cn/article/3QZ0o9Nmv*O0LoEPVRkN)

[@kyo](https://github.com/KyoLi)：在移动互联网时代，对于各家公司而言，什么东西最重要呢？我想大多数的答案应该是流量。本文当然不是讨论如何获取更多的流量等问题，毕竟那更多是产品运营的事情，而为流量做保驾护航的，就是网络。所以，如何优化网络，也是各厂纷纷探索的方向。对于流量越大的 App 而言，网络优化所带来的收益也越大。本文由百度 App 研发团队所写的[百度 App 网络深度优化系列]的第一篇，DNS 的优化，从百度这个亿级日活的 App 自身的实践中总结出来的，非常值得好好看下。

### 🌟 🐎 [Pure protocol factory for Interface Builder-based views](https://blog.hal.codes/ib-constructible)

[@looping](https://github.com/looping)：多人协作引起的代码合并冲突是我们使用 Storyboard 进行开发时常会遇到的比较头疼的问题了。避免这类协作问题的常用解决方案就是制定规范，规定一个界面用一个 Storyboard，并由单人维护。这样虽然解决了协作问题，但假如在写实例化代码时不进行优化，还是会存在一些不太友好的冗余代码，甚至硬编码。例如，`let controller = UIStoryboard(name: "MyViewController", bundle: Bundle(for: MyViewController.self)).instantiateInitialViewController() as? MyViewController`。

本文作者就分享了一种优化思路，他通过设计一个 UIViewController 的协议（protocol）IBConstructible —— 带有 nibName 和 bundle 这两个属性，利用 Swift 允许通过扩展（Extension）为协议提供默认实现的特性，使得最终实例化代码变得非常简洁，`let controller = MyViewController.fromNib`。

如果有在使用 Storyboard 进行开发的团队，但还没有对相关代码进行优化的话，可以参考本文提供的方案来处理，让代码变得更加简洁。如果已经优化过的，不妨也分享下自己的思路。同时本文的优化技巧也是可以用在很多代码重构的场景上的。

### 🐎 [RunLoop 实战：实时卡顿监控](https://juejin.im/post/5cacb2baf265da03904bf93b)

[@kyo](https://github.com/KyoLi)：虽然移动设备的性能越来越好，但为了追求更好的体验，卡顿依然是我们日常开发中不可忽视的问题。目前，各个公司都会采用各种三方库或者自己写的库来监控卡顿，但无论什么库，监控卡顿必然绕不开 Runloop。本文作者简单介绍了监控卡顿的原理，然后利用 Runloop 的特性制作了一个可以监控卡顿的 Demo。

### 🐎 [Indeterminate Types chuwith Codable in Swift](https://medium.com/makingtuenti/indeterminate-types-with-codable-in-swift-5a1af0aa9f3d)

[@极速男孩](https://github.com/ztlyyznf001) : Codable 是在 Swift 4 以后引入的一种序列化和反序列化的协议。本文主要介绍了两种对于在 Codable 协议中，处理不确定类型的两种方式：

1. 通过枚举去关联想要存储的不同类型的属性值。
2. 使用 `Any` 关键字去存储想要的类型。

本文在这里主要推荐使用 `Any` 关键字， `Any` 和用枚举的方法相比在保持类似的开发体验的同时，可以灵活的去修改。

> 由 [yuhanle](https://github.com/yuhanle) 推荐

### 🐎 [一篇文章读懂 HTTPS 及其背后的加密原理](https://mp.weixin.qq.com/s/3gI8avaaaEaBJjOKitN7Fw)

[@J_Knight_](https://github.com/knightsj)：作者以使用 HTTPS 的缘由为切入点，从对称加密和非对称加密的对比，数字证书，数字签名，以及 HTTPS 通信的建立流程这几个方面介绍了 HTTPS。

### 🐕 [Stubbing in pair with Swift compiler: a spy registration](https://medium.com/flawless-app-stories/stubbing-in-pair-with-swift-compiler-a-spy-registration-bbfdc1cf87a1)

[@zvving](https://twitter.com/zvving)：45 期我们曾介绍过 [Unit tests 中轻量级 stubbing 实现](https://medium.com/@londeix/stubbing-in-pair-with-swift-compiler-c951770a295b)，其中测试用例执行前注册 stub body 的过程略显繁琐。
如今作者更近一步，设计一套名为 **arguments spy** 的可插拔机制，尝试解决 Unit Tests 中动态修改 stub body 实现的困扰。对函数式编程感兴趣的同学不要错过。

## 工具

### [optionals](https://www.optionals.org)

[@张嘉夫](https://weibo.com/2949394297)：一个展示 Swift 可选型（optional）各种用法的网站。

### [onesignal](https://onesignal.com/)

[@邦Ben](http://weibo.com/linwenbang)：国外的一个集合型的服务（移动推送，Web 推送，内购，邮件），老套路，基础服务免费，高级服务氪金。因此，如果有海外业务的同学和开发个人 APP 的同学不妨看看。

## 代码

### [Solutions to LeetCode by Swift](<https://github.com/soapyigu/LeetCode-Swift>)

[@zvving](https://twitter.com/zvving)：算法已经成为各大公司面试必考项目。刷 LeetCode，无论是准备面试还是锻炼自己的算法和编程能力都很有帮助。网上 Swift 解法实现不多，这个版本相对完善，在代码规范、分类、时间（空间）复杂度梳理等方面可圈可点，值得参考。

LeetCode 已入驻国内，中文名[『力扣』](https://leetcode-cn.com)，可以一试。

相关阅读：

- [LeetCodeAnimation](https://github.com/MisterBooo/LeetCodeAnimation)

### [Codextended](https://github.com/JohnSundell/Codextended)

[@张嘉夫](https://weibo.com/2949394297)：让 Swift 的 `Codable` API 更容易使用的一套 extensions，赋予其类型推断（type inference) 能力。Codextended 既不是 wrapper 也不是全新的框架，而是用一种极其轻量的方式来增强 `Codable`。`Codable` 很强大也很方便，但如果你需要一定程度的自定义的话（例如转换部分 decoded data，或为某些键提供默认值），`Codable` 的标准 API 就会变得*相当*啰嗦。它没有充分利用 Swift 强大的类型推断能力，导致产生了很多不必要的重复代码。Codextended 就旨在解决这个问题。

### [Brooklyn](https://github.com/pedrommcarrasco/Brooklyn)

[@享耳先森](https://github.com/iblacksun)：受苹果 2018.10.30 发布会启发，设计并开源的一个屏保程序，非常漂亮，可在终端执行 `brew cask install brooklyn` 安装。

### [SecureDefaults](https://github.com/vpeschenkov/SecureDefaults)

[@小非86](https://weibo.com/xuyafei86)：SecureDefaults 是对 UserDefaults 的轻量封装，使用 Swift 编写，并额外支持 AES-256 加密（密钥 256 位）。如果你想改善 App 持久化数据的安全性，又执意要使用 UserDefaults 的接口，SecureDefaults 提供了 Keychain 之外的另一种灵活选择 。

## 书

### 🌟 🐎 [Swift 5.0 中文版官方文档](https://swiftgg.gitbook.io/swift/swift-jiao-cheng)

[@老峰](https://github.com/GesanTung)：上个月 [Swift 5.0](https://mp.weixin.qq.com/s/-fLVdoTz3lT5Kxnea0-Avg) 正式发布了，这是 Swift 发展史一次重要的迭代。SwiftGG 翻译组最近也更新了 [Swift 5.0 中文版官方文档](https://swiftgg.gitbook.io/swift/swift-jiao-cheng)，内容覆盖了 Swift 的基础语法结构以及各种高级特性，感兴趣的读者快来学习吧。

## 音视频

### 🌟 [ggtalk | 三组织揭秘：知识小集 x iOS 周报 x SwiftGG](https://talk.swift.gg/25)

[@Parsifal](https://weibo.com/parsifalchang)：知识小集 x iOS 周报 x SwiftGG 已经成为 iOS 圈子内为大家所熟知的三大社区组织。这一期 GGTalk 邀请到了我们三大组织的创始人 - 小集 [南峰子](https://weibo.com/touristdiary)，SwiftGG 的 [梁杰](https://weibo.com/numbbbbb)，以及我们周报团队的一代目 [卓同学](https://weibo.com/u/1926303682)，一起谈谈我们这三大组织的故事。

周报团队从 18 年 1 月份第 1 期到现在第 63 期，已经一年多了，期间除了春节等特殊节假日，没有断过更新。但周报其实在这一年多的时间里，也有遇到过不少小问题。我从去年 10 月份左右从老卓手上接过周报的运营工作，至今正好是半年。基于老卓打下的基础，还有周报 30 位编辑的一起努力，我们依旧在每期稳定地输出高质量内容，并尝试了掘金沸点、话题讨论和GitHub Release 等全新的方式，公众号在 [@Damonwong](https://weibo.com/damonone)、[@邦Ben](http://weibo.com/linwenbang) 和 [@红纸](https://github.com/nianran) 地运营下，也逐渐走上正轨。至此我也能说上一句不负所托。

虽然正如梁杰所说的 “组织总有尽头”，但我还是希望周报在未来的日子里还会有三代目、四代目……感谢我们三大组织的所有参与者，以及我们所有的读者和听众。

## 内推

老司机周报团队联合知识小集和 SwiftGG 翻译组收录了一份靠谱的内推职位。

如果你想**找工作**，点这里：https://www.yuque.com/iosalliance/article/bhutav

如果你想**招人**，点这里：https://www.yuque.com/iosalliance/article/ycyhf3

当然，也欢迎你关注我们每一期的周报，我们会在每期周报底部及时更新编辑内推岗位。

## 关注我们

我们开通了公众号，每期发布时公众号（OldDriverWeekly）会推送消息，欢迎关注。

![](https://github.com/SwiftOldDriver/iOS-Weekly/blob/master/assets/qrcode_for_wechat.jpg?raw=true)

同时也支持了 RSS 订阅：https://github.com/SwiftOldDriver/iOS-Weekly/releases.atom 。

## 说明

🚧 表示需翻墙，🌟 表示编辑推荐

预计阅读时间：🐎 很快就能读完（1 - 10 mins）；🐕 中等 （10 - 20 mins）；🐢 慢（20+ mins）


