- Tip: 统一隐藏 Type 的 property setter
- Receive: 在 App 运行时收集 code coverage 信息
- Algorithm: Divide Two Integers
Tip: 统一隐藏 Type 的 property setter
在编写程序时, 经常需要仔细设计一个 model 的各个 property 的读写性质. 通常, 为了方便, 我们会把 model 的所有 property 设为 var, 来允许我们的一部分代码对 property 进行延迟赋值或者其他修改.
1 | struct Model { |
然而, 在大型程序中, 我们并不希望所有该 model 的访问者都可以随意修改 property, 它们只需要使用 getter, 而不应该调用 setter. 于是, 有些情况下会选择给使用者提供另一个只读的 model.
1 | struct ClientModel { |
然而, 如果很多 model 都有这个需求, 将会导致 code 中出现很多重复的实现代码.
使用 Swift 中的 dynamicMenmberLookup 的 keyPath 静态版本, 可以大量简化这一工作: 我们只需要定义一个 generic 的 readonly wrapper, 就可以套用到任意的 model 类型上.
这里使用的 Swift 特性 dynamicMenmberLookup 可以起到类似 c++ 中重载 “.” 和 “->” 运算符的效果, 将对某个对象的 property access 转发到另一个内部对象上.
1 | @dynamicMemberLookup |
在上面的实现中, 我们只提供了接受 KeyPath
参数的 subscript, 而没有提供 WritableKeyPath
参数的版本, 从而在接口上消除了所有 property setter.
Receive: 在 App 运行时收集 code coverage 信息
最近参加公司内部的一次技术分享, 该分享介绍了一个工具, 可以在 App 测试过程中收集开发编写的代码的运行情况, 做到动态 code coverage 收集.
之前我只了解, 使用 Xcode 跑 Unit Test 时, Apple 会插入一些新的编译/链接选项, 给运行的 code 进行插桩, 并在 code 运行完后根据运行时的记录信息生成报告; 但是我并不知道运行中的 App 本身是否能获取到自身运行的情况. 经过一些 searching, 原来 LLVM 是支持这一操作的, 也有官方文档详细描述了使用姿势. 核心要点摘录如下:
- Source-based Code Coverage 描述了主要的 code coverage 流程
- Using the profiling runtime without static initializers这一节主要描述了如何在运行时获取到 profile 信息
__llvm_profile_set_filename
可以设置 profile file 的路径__llvm_profile_write_file
调用一次可以把当前的 profile 写到指定的路径
- llvm 提供了 llvm-profdata 和 llvm-cov 等工具来处理生成的 profile 文件, 并解析成可读的 JSON 格式
- Using the profiling runtime without static initializers这一节主要描述了如何在运行时获取到 profile 信息
- Clang 文档也有关于 profile 的一些例子, 并且详细阐述了一些 compiler flag 的用法.
Algorithm: Divide Two Integers
题目
来自 leetcode.
1 | Given two integers dividend and divisor, |
实现
禁止乘法和除法的情况下, 理论上计算 只需要在 上不断减去 , 直到无数可减. 但这样性能不高, 实际上随着商的位数增加, 每次可以减的可以比 更多. 如果 , 把 c 按二进制方式写成 , 每一位的贡献是后一项的两倍.
1 | func divide(_ dividend: Int, _ divisor: Int) -> Int { |