# 老司机 iOS 周报 #56 | 2019-02-25

![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) 提出。

## 话题

### 🌟 🐢 [关于 Swift ABI 稳定 ](https://github.com/SwiftOldDriver/iOS-Weekly/issues/1183)

迟到三年的 ABI 稳定终于要来了。

苹果发布了 *[ABI Stability and More](https://swift.org/blog/abi-stability-and-more/)* 和 *[Evolving Swift On Apple Platforms After ABI Stability](https://swift.org/blog/abi-stability-and-apple/)* 两篇文章来阐述 Swift 5 发布以后 ABI 相关的内容所带来的改变。看不懂英文的也不要怕，细心的喵神帮我们做了一个很棒的总结: *[Swift ABI 稳定对我们到底意味着什么](https://onevcat.com/2019/02/swift-abi/)*。

Swift ABI 可以说是 Swift 的一个里程碑事件，让跨平台的能力更上了一层，但是 Swift ABI 对于 iOS 开发者使用来说，影响不是很大，有很多开发者误把 API 稳定当成了 Swift ABI 稳定。对于开发者来说，只有 API 稳定了，才是真正意义上的不需要迁移适配了。

如果不知道 Swift ABI 是什么的朋友，可以看看苹果去年发布的 *[Swift ABI Stability Manifesto](https://github.com/apple/swift/blob/master/docs/ABIStabilityManifesto.md)*。同时 **[泊学](https://boxueio.com)** 也做了一个很棒的翻译版: *[译：Swift ABI (一)](https://boxueio.com/blackboard/1)* 和 *[译：Swift ABI (二)](https://boxueio.com/blackboard/2)*。

**最后，关于 Swift ABI，你有什么看法，可以在我们的 [Github Issue](https://github.com/SwiftOldDriver/iOS-Weekly/issues/1183) 上，发表你的看法，与周报编辑一起讨论。**

## 新闻

### [Swift 5.1 发布计划](https://github.com/SwiftOldDriver/iOS-Weekly/issues/1161)

Swift 团队近日在博客里更新了 5.1 的发布计划，这个版本的主要目标是达成 [Module Stability](https://forums.swift.org/t/plan-for-module-stability/14551)，简单的说就是 Module 接口的向前兼容。

另外知识小集也在第一时间[进行了翻译](https://mp.weixin.qq.com/s/2FYhe4gGTCMZL82IOYK7kg)，推荐阅读这一篇。

### [It’s time to stop using index(of:)](https://www.hackingwithswift.com/articles/177/its-time-to-stop-using-index-of)

`SE-0204` 在 `Swift 4.2` 实现
- 增加 `lastIndex(of:)`
- 增加 `lastIndex(where:)`
- `index(of:)` 改名 `firstIndex(of:)`，并且废弃原方法
- `index(where:)` 改名 `firstIndex(where:)`，并且废弃原方法

## 文章

### 🌟 🐢 Swift5 新特性 @dynamicCallable 带来的动态魔法

一年前周报的第一期我们曾经提过：[Swift 快要可以和 Python 无缝交互了](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171204/042029.html)，一年后的今天伴随着 Swift5 新特性 `@dynamicCallable` 的发布，『用 Swift 写 Python 变成现实』。

起源是 Chris Lattner 大神的两个提案：`@dynamicMemberLookup` 提供动态查找成员的能力（Swift4.2），`@dynamicCallable` 则提供动态方法调用的能力（Swift5）。很难想象，两个语法糖重新定义语言动态性，让人看到 Swift 成为胶水语言的可能。

下面三篇系列文章带我们感受语法糖带来的神奇魔法：

- [#1 Unix Tools as Swift Functions](http://www.alwaysrightinstitute.com/swift-dynamic-callable/)

	一层薄薄的封装让所有 Unix Tools 变成 Swfit 方法，提供这样的调用方式：`shell.env()`, `shell.ls("-a", "-l")`, `shell.python("--version")`；
- [#2 Swift/ObjC Bridge](http://www.alwaysrightinstitute.com/swift-objc-bridge/)

	基于 @dynamicCallable 轻松实现一套 Swift - Objective-C 的桥接。实现思路类似 [PyObjC](https://pythonhosted.org/pyobjc/)
- [#3 Mustasheable](http://www.alwaysrightinstitute.com/mustacheable/)

	为模板语言[Mustache](http://mustache.github.io/)的生成器提供简洁优雅的调用方式。

相关阅读：[细说 Swift 4.2 新特性：Dynamic Member Lookup](https://juejin.im/post/5b24c9896fb9a00e69608a71)

### 🌟 🐎 [架构师思维](https://limboy.me/tech/2019/02/16/architect-mindset.html)

架构师一词听起来就是个很高端的 Title，在职业生涯的多数时候，在我心里都是高山仰止般的存在。尽管不同的公司对架构师的要求也许不一样，但印象中应该都是技术特别出众的人。那除了技术出众之外，又应该具备什么样的架构师思维呢？本文作者从开发者和开发两个方向阐述了什么才是架构师思维，值得去细细揣摩，带着这个思维，也许你会有新的发现和努力的方向。

### 🐎 [Behind the Proposal — SE-0200 Enhancing String Literals Delimiters to Support Raw Text](https://swift.org/blog/behind-se-0200/)

`SE-0200` 提案中增强字符串分隔符支持原始文本的能力。

- 支持多行，并且同时具备Swift原有的字符串功能（如插值），示例：
`"""
line1
\(line2) 
"""`

- 为了覆盖边转义字符缘特殊情况，参考了 `Rust` 的设计，支持自定义分隔符声明原始字符串，同时支持插值。`#""#` 是将原本 `\` 转义分隔符修改为 `\#`。
    - `#"\#(val))"#`，等同于以往的`\(val)`。`#"\n"#` 输出 `\n`。
    - `###"\nline"###`，转义分隔符是 `"\####"`，输出 `\nline`。

### 🐢 [Swift 5 Exclusivity Enforcement](https://swift.org/blog/swift-5-exclusivity/)

在 2017 年初，Swift 社区发了一篇长文介绍 Swift 4 将在内存安全方面做一些改进，@onevcat 翻译了此文 [所有权宣言 - Swift 官方文章 Ownership Manifesto 译文评注版](https://onevcat.com/2017/02/ownership/) 建议细读。

上文中提到的改变大多已在 Swift 4.x 落地，即将发布的 Swift 5 中，对「独占性访问」进行了增强：`在 Release 模式运行也默认开启。`

Swift 4 中，只有 Debug 模式下，Runtime 会做「独占性访问」的检查(编译时 Debug 与 Release 都会检查，但编译检查可能覆盖不全)，Swift 5 中， Release 模式 Runtime 也默认开启(可手动关闭)。文章仔细介绍了这个改变可能带来什么问题，以及如何应对。

### 🐎 [How many apps use Swift in 2019?](https://blog.andrewmadsen.com/post/182862756395/how-many-apps-use-swift-in-2019)

文章作者对 App Store 上美区 Top 110 的 App 进行了分析，来看到底有多少 App 使用了 Swift。结果上看，目前 Top 110 的 App 使用 Swift 和未使用 Swift 基本处于对半开的状态。

大公司切换 Swift 和小公司切换 Swift 比起来，难度要大很多，所以对于这样的结果，也不算惊讶。希望再过一年，Swift 的比例能够有进一步的增长，毕竟 ABI 稳定了。

### 🐕 [Painless UI Testing in iOS: Mocking the Network](https://code.egym.de/painless-ui-testing-in-ios-part-1-mocking-the-network-ffbd6ab4809a)

本文是 Painless UI Testing in iOS 系列的第一篇文章。该系列打算介绍三种方法来让 UI 测试变得更快更可靠。第一种在本文做了介绍，第二种是在第二篇介绍的 [Stubbing the Navigation](https://code.egym.de/painless-ui-testing-in-ios-part-2-stubbing-the-navigation-c5984e728f7e)。但是该系列的第三篇还没有发布，大家可以关注他们的技术博客 [eGym Software Development](https://code.egym.de/)。本系列的作者按设计思路附上代码的方式把他的想法分享的很详细，是非常值得学习和借鉴的，热衷 UI 测试的同学不可错过。

### 🚧 🐕 [Deep Diving React Native Debugging](https://medium.com/@shaheenghiassy/deep-diving-react-native-debugging-ea406ed3a691)

在开发 React Native 应用时，我们可以通过开启 `Debug JS Remotely` 来实现在 Chrome 中调试 JS，包括断点调试、查看堆栈信息、变量状态等，有时候我们可能还会在调试时遇到红屏错误 `Runtime is not ready. Make sure your packager server is running.`，但是不知道这背后都发生了什么。我们往往对这些每天日常开发中接触的东西既熟悉又陌生，不妨跟着这篇文章读读源码并调试一下，一切都将豁然开朗。

> 由 [@ShannonChenCHN](https://github.com/ShannonChenCHN) 推荐。

### 🐕 [分析一次有意思的需求——HTML 代码注入](https://juejin.im/post/5c6f949b51882562260d37fa)

在 iOS Hybrid APP 开发中我们经常会有这样的需求： 通过 WebView 实现 JavaScript 与 Objective-c 交互。本文作者以 WKWebView 访问了一个 HTML 页面，获取用户的所有输入信息这样的问题为例，将需求拆解为如下几部分，最终解决问题。

1. HTML 和原生交互
2. HTML 获取指定元素
3. 通过 JavaScript 动态为 HTML 元素添加事件
4. 通过 WKWebView 向 HTML 注入 JavaScript 并调用 原生代码

作者通过逐步拆解需求，把抽象的问题分解成各个小问题的组合，然后逐个分析验证，最终解决相对复杂的问题。其实这正是如何分析具体的需求，并将其转换为代码的一个过程，感兴趣的读者可以跟着作者思路读一读，应该会有所启发。

> 由 [@chouheiwa](https://github.com/chouheiwa) 推荐。

### 🐢 [How I failed 39 interviews and what I’ve learned](https://medium.com/flawless-app-stories/how-i-failed-39-interviews-and-what-ive-learned-515c8e6c4b53)

一个大学计算机系二年级在校生从 39 次面试失败经历中的总结，对于大部分软件开发工作者而言，去一些大厂工作都是一个目标。作者打小就梦想进入 Google Facebook 等这些大厂工作，而这篇文章总结了他在校期间面试大厂屡战屡败、屡败屡战的经历。
老司机推荐给大家，希望给正在努力亦或是正在迷茫的你有所帮助。

### 🐕 [Demystifying UIKit Spring Animations](https://medium.com/ios-os-x-development/demystifying-uikit-spring-animations-2bb868446773)

Spring 弹簧动画从 iOS 7 开始就成为了公开 API，但当时的 damping-duration 接口非常不自然，iOS 10 发布 `UISpringTimingParameters` 和 `UIViewPropertyAnimator` 之后有所好转，但要制作出优秀的弹簧动画仍然不是一件容易的事。这篇文章会为你介绍究竟什么是弹簧动画、背后的工作原理以及如何调试出恰到好处的动画。

### 🐎 [Swift 5 字符串插值之美](https://swift.gg/2019/02/21/the-beauty-of-swift-5-string-interpolation/)

本译文介绍了 String 类型对 `ExpressibleByStringInterpolation` 协议的三种扩展实现，以精确控制字符串插值的打印方式。`ExpressibleByStringInterpolation` 协议在 Swift 3 时被废弃，如今被以一种更优雅、扩展性更强的方式重新实现。建议同时阅读一下 [SE-0228](https://github.com/apple/swift-evolution/blob/master/proposals/0228-fix-expressiblebystringinterpolation.md) 这个提案，对比了解下新旧两种实现方式，以及新的实现方式所带来的可扩展性和性能改进。也可以看下 [HTML，LocalizableString，SQLiteStatement](https://gist.github.com/brentdax/0b46ce25b7da1049e61b4669352094b6) 三种非 String 类型的扩展实现。 

### 🐎 [唯品会 iOS 代码覆盖率的应用实践](https://mp.weixin.qq.com/s/mTXMbm0c-nCWZ8v8D1-QAA)

在快速迭代的这个软件开发生态下，量化测试数据成为软件测试中必不可少的一步。

本篇中，作者将一步步剖析，iOS 代码覆盖率的应用。文中的主要步骤可以拆分成一下几个部分。

- 在编译过程中，利用 LLVM 可以使用 gcda/gcno 记录代码覆盖率的特性，进行中间代码插桩
- 在程序执行过程中，将记录文件刷入内存当中，利用 HTTP 接口上传服务器
- 将 LCOV 作为记录文件分析工具，生成可视化的报表数据

相较于传统的行/函数/分支覆盖率外，文中新增了行差异覆盖率。将覆盖率文件进行预处理，新增差异代码行数相关属性，达到支持差异/多版本合并。

> 如果对于 GCC 插桩想要有所了解可以看这个博主的一系列研究 [链接](https://so.csdn.net/so/search/s.do?q=GCC%20%E6%8F%92%E6%A1%A9&t=blog&u=livelylittlefish)

## 工具

### 🐕 [Introducing the sourcekitd Stress Tester](https://swift.org/blog/sourcekitd-stress-tester/)

Sourcekitd 是为 Xcode 和最近发布的 SourceKit-LSP 的编辑器核心功能提供数据支持的工具。如 Swift 文件的代码补全，语法高亮和重构等。为了帮助改善其健壮性，本文介绍了一个新引入的工具，即 “Sourcekitd 压力测试工具”。在过去几个月中，它帮助找到了 91 个可复现的 Sourcekitd 崩溃，断言失败和挂起。 这篇文章介绍了 Sourcekitd 的实现，如何在 Swift CI 和 PR 测试中部署，以及 Swift 开发人员如何在自己的项目中运行它，以帮助改善每个人的 Swift 编辑体验。

## 代码

### 🌟 [MicroKernel](https://github.com/mrriddler/MicroKernel)

MicroKernel 是一个客户端微内核架构，它把业务和基础都视作插件，形成一个插件化微内核架构。对于业务，一切其他模块的业务和基础都是注入的依赖。

MicroKernel 遵守了整洁架构 (clean architecture)、六边形架构 (hexagonal architecture) 等架构的主旨，架构以代码变更的原因和频率形成边界和层次。

分为以下几个层次:

- MicroKernel：App的驱动，提供MicroApplication管理、通信机制、依赖注入、路由等。
- MicroKernelService：贯穿App的基础能力服务，提供基础能力的领域抽象，不包括具体的技术选型，不必拘泥于依赖注入形式。
- MicroApplicationService：贯穿App的业务服务，从复用角度聚合，包括其整体业务方案，比如，分享、登录、支付等。
- MicroApplicationCoordinator：解开MicroApplication之间耦合的协调器。
- MicroApplication：独立的业务，从功能角度聚合，在架构中称作应用，其形式包括Native、H5、Hybrid、小程序等。
- MainApplication：整个App的架构注册、配置，以及外部渠道的对接。

> [MicroKernelDemo](https://github.com/mrriddler/MicroKernelDemo) 是作者通过模拟一个简单的业务场景，以帮助读者熟悉 MicroKernel 背后的概念和使用的实践 demo。

### [Aiolos](https://github.com/IdeasOnCanvas/Aiolos)

Aiolos 是一个受浮动面板启发的 Swift UI 框架，已在 iOS 11 中的地图应用中引入。它完全由手势驱动，并自动响应屏幕键盘，与许多其他开源面板解决方案相比，Aiolos 被设计为始终可见的子视图控制器，因此不使用 iOS 的自定义视图控制器转换 API。可通过 Carthage 集成到项目中，使用简单便捷，感兴趣的同学可以尝试一下。

### [EasyTransitions](https://github.com/marcosgriselli/EasyTransitions)

EasyTransitions 是一个简单易用的转场动画库，可以帮助开发人员使用协议中定义的简单函数创建自定义交互式转换，避免使用 UIKit 中的多个转换 API 进行实现的麻烦。

特性
- 自定义过渡简单设置
- 支持模态演示，UIPresentationController 和 UINavigationController 过渡
- 具有多个平移手势方向的 1 行中的交互式转换支持
- 3 个自定义转换作为示例
- iOS 和 tvOS

EasyTransitions 库很实用，有需要感兴趣的读者可以看看，不过该库只提供了 swift 版本哦！

## 音视频

### [Swift Community Podcast #3 - Result Type, Character Literals and Swift Evolution](https://www.swiftcommunitypodcast.org/episodes/3)

Swift Community Podcast 是 Swift 开源社区举办的讨论 Swift 语言特性与应用的电台节目，基本可以认为是 Swift 的官方 Podcast，第三期的主持人是 Swift 之父:Chris Lattner, 还有两位嘉宾：提出了 Result type，同时也是 Alamofire 维护者之一的 Jon Shier，以及Kelvin Ma，目前还是一名在校学生。三个人首先讨论了 Swift 的开源历史，有哪些重要的时间节点，然后从 Swift 的错误处理的前世今生开始聊，引出了 Result type 的必要性。最后也讨论了 Character Literals 提案的一些趣事。整体氛围比较轻松，尤其是 Jon Shier 吐字非常清楚，非常适合英文不太好的同学（比如我）听。基本都能听懂。

### [ggtalk | 2019 准备学什么新技术？](https://talk.swift.gg/18)

作为积极上进，互相攀比只有攀比学习的 iOS 圈，想必 iOS 程序员们最关心的话题的就是 9102 年，我们到底应该学什么。当然这个话题是因人而异的，ggtalk 这期节目邀请了 SwiftGG 翻译组的蓉老师和莲叔，和帮主一起聊了各自在 9102 年的学习计划，可以提供一定的参考给广大学习焦虑的 iOS 同学。

## 内推

- [上海-小红书-高级/资深/专家 iOS开发&架构](https://job.xiaohongshu.com)：参与小红书App日常功能/架构 (APM \ Crash \ Security) 开发与维护；业务高速成长中, 团队年轻活泼, 技术氛围浓厚, 坐标上海市中心新天地地铁口。推荐或简历可直接发到 cli2@xiaohongshu.com。

- [北京-百度网盘 持续招 iOS 开发](https://talent.baidu.com/external/baidu/index.html#/jobDetail/2/102507)：社招、应届、实习均可。项目在技术上很有挑战性，团队技术氛围极好。诚心希望各路大神前来切磋，也欢迎计算机基础好的小白来共同学习。简历发邮箱 xuyafei01@baidu.com，暂不考虑的也欢迎微博私信 [@小非86](https://weibo.com/xuyafei86) 聊聊~

- [北京-蚂蚁金服 招iOS/安卓/前端开发](https://job.alibaba.com/zhaopin/position_detail.htm?trace=qrcode_share&positionCode=GP031268&from=timeline&isappinstalled=0)：负责支付宝会员及帐号业务线，地点北京国贸，金台夕照地铁站出口 100 米。有兴趣的同学欢迎将简历发送到：weijing.wdf@alibaba-inc.com / weijing.wdf@antfin.com （同一个邮箱）或者微博私信 [@折腾范儿_味精](https://weibo.com/agvicking) 了解情况。

- 上海即刻：如果你认识聪明勤奋、胆大心细、有追求的工程师，那就来加入我们吧！任何推荐或简历可直接发给 Jason（即刻 iOS leader）: jasy@okjike.com，或微博 [@JasonYuh](https://weibo.com/jasonyuh)。

- [杭州奇志科技招聘 iOS、前端](https://www.lagou.com/gongsi/34872.html)：奇志科技自 2016 年起通过行业无人机协同工作流 Mesh 进入物联网与人工智能领域， 并成功为房地产、建筑、测绘、电力巡检等行业提供无人机解决方案。感兴趣可以微博上私信 [@没故事的卓同学](https://weibo.com/u/1926303682) 了解。

- [深圳头条研发中心诚招各路 iOS 好手一起做取悦自己的项目](https://job.toutiao.com/2018/spring_referral/?token=alPR8WCv8nnnc5QqtsyKjw%3D%3D&key=MTY1MDMsMTg0MTQsMjA1MjAsMTk1NjEsMTU2ODksMTc0ODk%3D)：如想了解更多深圳头条的信息，可以加小T微信：tomtan，切磋技术和聊情怀都可以喔~~~~

- [北京字节跳动 iOS 团队持续招人中](https://job.toutiao.com/society)：简历可以发送到邮箱 raozhizhen@gmail.com，或者添加我（[@AidenRao](https://weibo.com/AidenRao)）的微信 jingmu1994 了解更多公司及岗位信息。

- [北京百度教育事业部招 iOS 开发](https://www.baidu.com/s?wd=百度)：百度教育事业部，地点：北京西二旗。部门下面有百度阅读，百度文库，百度爱听等 App 产品。团队技术氛围浓厚，有兴趣的同学欢迎将简历发送到我的邮箱：lizelei@baidu.com。

- [深圳 - 格隆汇 iOS / Android / 前端](https://www.lagou.com/gongsi/j84043.html)：公司方向是投研资讯，目前正在稳步扩张中，各个级别的工程师都有需求。任何推荐或者简历都可以发送到我邮箱：[chenkem@gmail.com](mailto:chenkem@gmail.com)，同时也欢迎大家[私信我](https://t.me/kemchenj)了解更多信息。

## 关注我们

我们开通了公众号，每期发布时公众号（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 。

## 本期编辑

[@四娘](https://kemchenj.github.io)，[@享耳先森](https://github.com/iblacksun)，[@Damonwong](https://weibo.com/damonone)，[@折腾范儿_味精](http://weibo.com/agvicking)，[@张嘉夫](https://weibo.com/2949394297)，[@Parsifal](https://weibo.com/parsifalchang)，[@aaaron7](https://weibo.com/aaaron7)，[@kyo](https://github.com/KyoLi)，[@tom510230](https://xiaozhuanlan.com/u/6682065345)，[@anotheren](https://anotheren.com)，[@水水](https://www.xuyanlan.com)，[@looping](https://github.com/looping)，[@老老老老老老老驴](https://weibo.com/u/6090610445)，[@小非86](https://weibo.com/xuyafei86)，[@邦ben](http://weibo.com/linwenbang)，[@红纸](https://github.com/nianran)，[@含笑饮砒霜](http://chinafish.news)，[@JimQ](https://github.com/waz0820)，[@老峰](https://github.com/GesanTung)，[@zvving](https://github.com/zvving)，[@J_Knight_](https://github.com/knightsj)

## 说明

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

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


