Xcode 10.1 新特性及解决的问题

距离 Xcode 10.1 正式版发布已经将近一个月了,我们今天重新来回顾一下 Xcode 10.1 的新特性,以及已解决的问题和存在的问题。

本文主要参考了《Xcode 10.1 Release Notes》进行整理,同时你也可以查阅《Xcode 10 Release Notes》获取更多关于 Xcode 10 的细节。

接下来我们将以新特性(New Features)、已解决的问题(Resolved Issues)、已知问题(Known Issues)等几方面来介绍 Xcode 10.1 在各模块上的更新。

1. General / 通用

新特性

  • 支持 arm64e 处理器架构(预览版)

如果你想尝试尚处于开发者预览版的 arm64e,请在 Xcode 项目编辑器中选择你的 iOS app 对应的 target,在 Build Settings 中找到 “Architectures” 设置项,选择 “Other…” 选项,然后添加手动添加 arm64e 到 architectures 列表中。

注:目前 App Store 和 TestFlight 并不接受包含 arm64e 的提交,所以当我们 Archive 后在 Organizer 窗口要向苹果提交发布时,Xcode 会自动移除掉 app 包中 arm64e 的内容。

已解决的问题

  • 菜单中 Navigate > Open in… 的导航栏 UI 不再将窗口中的各个 tabs 显示为单独的窗口,每个窗口都有一个 tab。

  • xed 工具现在使用由当前 xcode-selectDEVELOPER_DIR 环境变量指定的 Xcode。

2. Apple Clang Compiler / 苹果 Clang 编译器

已解决的问题

  • 对 iOS 12.1 beta 2 中的 libunwind 库进行修改,解决了在 iPhone XS 和 iPhone XS Max 上运行少部分 app 的问题。

3. Asset Catalog / 资源目录

已知问题

  • 项目中如果包含了 asset catalogs 并使用 Xcode 10.0 或者更高版本的构建的 app,且其 Deployment Target(指最低支持的系统版本)设为 iOS 9.0、9.1 或者 9.2 时,会生成与这些 iOS 版本的运行时不兼容的内容(具体表现为:在系统版本为 9.0 ~ 9.2.1 之间的真机设备上通过 App Store 或者 TestFlight 下载安装该 app 并运行,会出现偶现的 Crash)。

注:关于这个问题,相信大家已经很熟悉了,网上有很多讨论,我们之前也发了几条相关的小集。它是在 Xcode 10.0 上开始出现的,而在 Xcode 10.1 刚发布时,苹果声称已经解决了,后面大家纷纷表示这个问题仍然存在。不过根据微博上的最新消息和小伙伴们的亲自验证,苹果已经在服务端解决了这个问题,开发者通过 Xcode 10.1 打的 ipa 包在上传到 App Store Connect 后台,苹果在处理包的过程中会自动修复。

已解决的问题

  • 增加 40mm 和 44mm 的孔(wells)用于解决指定正确的图标大小的难题。

4. Build System / 构建系统

已解决的问题

  • 新的构建系统支持“按需资源”(On Demand Resources,ODR)。

  • 修复了问题:在为 .xib 文件或 storyboards 使用基本本地化时,不会将与基本文件关联的各个本地化的 .xib 文件或 storyboards 编译到产品中。

5. Debugging / 调试

新特性

  • 对于异常断点(Exception Breakpoints)的断点编辑器增加了一个 “ignore count” 字段。

6. Devices / 设备

已解决的问题

  • 运行 iOS 12 或更高版本的设备从 “Devices” 窗口中请求获取屏幕截图的问题。

7. Interface Builder / 界面构建工具

新特性

  • 现在,在画布中拖动控件(Control-dragging)以添加约束总是包括所有四个方向,而不仅仅是最接近拖动方向的方向。

已解决的问题

  • 修复了问题:在将视图与 UIScrollView 的子视图添加约束时, Auto Layout 会错误报告问题。

  • 提高了画布(canvas)的性能:当底部设备栏在 iPhone XS、iPhone XS Max 和 iPhone XR 之间切换时。

  • 修复了导致预览助手编辑器(Preview assistant editor)中监视内容布局与设备栏选择不匹配的问题。

  • 现在,当启用 @IBDesignable 视图时,将使用新的构建系统进行编译。

8. Simulator / 模拟器

已知问题

  • 如果有另一个进程,例如 simctl,在模拟器正在打开时关闭了模拟的设备,则模拟器在下次启动设备时无法正确地重新连接到模拟器。如果你安装了多个版本的 Xcode,则在其他版本的 Xcode 中运行模拟器是可能也会遇到这个问题。

临时解决方案:退出并重新启动模拟器。要在不关闭所有模拟器的情况下退出,请先按住 Option 键并选择 Simulator > Quit Simulator…,然后在出现的对话框中选择 “Keep Running”。

9. Swift Compiler / Swift 编译器

已知问题

  • 如果你在一个类的实例对象上通过使用 protocol 或 extension 中定义的 nonmutating setter 来间接修改属性,则 Swift 编译器可能会出现错误编译:在调用该属性的 getter 方法之后就直接释放该实例对象。这可能会导致程序崩溃或在运行时出现不可预测的行为。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
protocol SomeProtocol { }
class SomeClass: SomeProtocol { }

extension SomeProtocol {
var someNonmutatingProperty: CGPoint {
nonmutating set { _ = self }
get { return .zero }
}
}

// Might be miscompiled, deallocating SomeClass() too early.
SomeClass().someNonmutatingProperty.x = 42

临时解决方案:将该操作分解为多个语句,以便 get 和 set 操作在不同的语句中发生:

1
2
3
4
5
6
let someObject = SomeClass()
// First get the nonmutating property value.
var temp = someObject.someNonmutatingProperty
temp.x = 42
// Then modify it.
someObject.someNonmutatingProperty = temp

已解决的问题

  • Xcode 中的 Playgrounds 不再记录关于在运行时类型无法解码的字段的信息。

  • 现在编译 Swift 代码时会始终报告导致任何失败的错误。例如,之前可能会发生诸如 “Command CompileSwiftSources failed with a zeroo exit code” 之类的消息,而没有伴随的失败原因。

  • 包含空格的长文件路径将不会再导致构建失败。

  • NSBundle 类的 bundleForClass: 初始化方法现在与 Swift 类保持一致,包括即使不在最新的操作系统版本上运行。

  • 现在可以将以函数类型作为参数的泛型类的 “let property” 成功传递给另一个函数或方法。

1
2
3
4
5
6
7
8
class A<B> {
let function: (B) -> B
}
func takeFunction(_: (Int) -> Int) {}

func passFunction(from a: A<Int>) {
takeFunction(a.function)
}
  • 对嵌套上下文中(nested context)的捕获值所做的更改现在将反映在外部上下文中(outer context)。

  • 现在可以成功调用一个在协议类型(protocol type)的值上返回 Self 的变异方法(mutating method):

1
2
3
4
5
6
7
protocol Example {
mutating func test() -> Self
}

func foo(x: inout Example) {
_ = x.test() // No longer crashes the compiler sometimes.
}
  • 编译器现在可以成功地将一个异构类对象(heterogeneous class objects)数组生成为 AnyObject 数组:
1
2
3
func f(_: [AnyObject])

f([NSObject.self, NSString.self])

10. Swift Standard Library / Swift 标准库

已解决的问题

  • FixedWidthInteger 协议中的 unsafeAdding(_:), unsafeSubtracting(_:), unsafeDivided(by:), 以及 unsafeMultiplied(by:) 等方法已弃用(deprecated),并将在以后的版本中删除。

这些方法在溢出条件下会产生未定义的行为。因此在算术运算的情况下,可以使用 assertaddingReportingOverflow(_:) 方法或者 &+ 运算符的组合,这两者都会在溢出的情况下有明确定义的结果。

11. Source Control / 代码控制管理

已解决的问题

  • 当从 GitLab.com 或者 GitLab 自托管账户进行克隆(cloning)仓库时,组织仓库(organizational repositories)目前可以与个人仓库(personal repositories)一起显示了。

12. Testing / 测试

已知问题

  • 当开启并行化测试(test parallelization)时,性能分析测试(profiling tests)的结果不能正确地表现。

临时解决方案:当进行分析测试时可以通过如下方式禁用并行测试:在 Xcode 菜单栏中打开 Product > Scheme > Edit Scheme… > Test > Info,选择测试 target 旁边的 “Options” 按钮,然后禁用 “Execute in parallet” 复选框。

已解决的问题

  • 使用旧版构建系统(legacy build system)的项目中的 UI 测试,目前可支持在 iPhone XS 和 iPhone XS Max 上运行了。

  • 如果一个 UI 测试的目标 app 在模拟器上进行测试期间崩溃了,则现在可以将其正确地报告为测试失败,而不是像之前那样被错误地视为成功测试,或者显示有关 “Application state unknown” 失败信息。

  • Xcode 10.1 beta 2 及更高版本支持在运行 iOS 12 beta 版的设备上进行 UI 测试。

  • 修复了如果在测试已经开始后的任何时刻添加观察者,则此时添加到 XCTestObservationCenter 共享实例对象上的观察者的 testBundleDidFinish: 方法不会被调用的问题(例如:在所有当前注册的观察者上调用了 testBundleWillStart: 方法之后)。

  • 当接收器(receiver)是一个菜单项或者菜单项的子视图时, XCUIElement 类的 clickhover 方法现在可以自动滚动菜单了。

参考连接

注:本文翻译内容如有描述不准确的地方,请参考上述英文原文。