Swift 等同于 Objective-C 的“#ifdef __IPHONE_11_0”是什么?
What's the Swift equivalent of Objective-C's "#ifdef __IPHONE_11_0"?
我想使用 Xcode 9 将 iOS 11 代码添加到我的项目中,同时保留使用仅支持 iOS 的 Xcode 8 编译项目的选项10.
在 Objective-C 中,我可以通过使用预处理器指令来检查是否定义了 __IPHONE_11_0
来做到这一点。如果我使用早于 iOS 11 的 Base SDK 进行编译,这将隐藏代码。像这样:
#ifdef __IPHONE_11_0
if (@available(iOS 11.0, *)) {
self.navigationController.navigationBar.prefersLargeTitles = YES;
}
#endif
在 Swift 中有没有办法做到这一点?
if #available(iOS 11.0, *)
不起作用,因为这是运行时检查。
iOS 11 SDK 附带 Swift 3.2(或 Swift 4),因此您可以使用 Swift 版本检查来完成同样的事情:
#if swift(>=3.2)
if #available(iOS 11.0, *) {
…
}
#endif
这是Apple建议的解决方案:
if #available(iOS 11.0, *) {
// iOS 11 specific stuff here
} else {
// non iOS 11 stuff here
}
请参考this resource(更多详情请观看标记6:50上的视频)
我明白了。我有一个旧的 Mac 我喜欢使用它,它对 Xcode 9 来说太旧了,所以我希望有时也能够在 Xcode 8 下编译我的项目。
但是如果你只想支持 iOS 10 和 iOS 11,简单的方法是将 Xcode 目标的最低 SDK 设置为 10.0,并且始终使用 iOS 11 SDK 进行编译。 Swift 在这种情况下会为你工作,并给你语法错误,除非你正确使用 if #available(iOS 11.0, *) {
您仍然可以在 iOS 10 和 iOS 11 下进行测试,而无需为 Xcode 8 操心。
从Xcode8的角度来看,你是在试图从未来编译源代码。 Xcode 8.
没有好的解决方案
展望未来,这里是解决方案:
在Xcode9.3(Swift4.1)中,你可以说:
#if canImport(MagiciOS12Kit)
if #available(iOS 12.0, *) {
MagiciOS12Class.standard.method()
}
#endif
并且您的代码仍将在 Xcode 9.3 下编译,但会跳过未来需要假设的 Xcode 10.0 或更高版本的内容。
#if canImport(moduleName) 仅在 Swift 4.1 中添加,Xcode 8 无法处理。但即便如此,这也仅适用于 Apple 未来添加的整个模块。如果 Apple 只是用新方法扩展现有的 class,就像在你的 navigationController.navigationBar.prefersLargeTitles 中一样,你仍然无法测试 prefersLargeTitles,但是你可以找到苹果与 prefersLargeTitles 同时引入的另一个框架,并使用 #if canImport(... ).
如果你想把条件放在函数之外,你可以像下面那样做。
@available(iOS 11.0, *)
func functionName() {
// function contents
}
你可以实现,像下面这样的功能
@available(iOS 11.0, *)
func myFunction() {
// function defination
}
或者如果你想检查内部函数写这个
if #available(iOS 11.0, *) {
// iOS 11 specific stuff here
} else if #available(iOS 10.0, *) {
// iOS 10 specific stuff here
} else {
// non iOS 11 & 10 stuff here
}
我想使用 Xcode 9 将 iOS 11 代码添加到我的项目中,同时保留使用仅支持 iOS 的 Xcode 8 编译项目的选项10.
在 Objective-C 中,我可以通过使用预处理器指令来检查是否定义了 __IPHONE_11_0
来做到这一点。如果我使用早于 iOS 11 的 Base SDK 进行编译,这将隐藏代码。像这样:
#ifdef __IPHONE_11_0
if (@available(iOS 11.0, *)) {
self.navigationController.navigationBar.prefersLargeTitles = YES;
}
#endif
在 Swift 中有没有办法做到这一点?
if #available(iOS 11.0, *)
不起作用,因为这是运行时检查。
iOS 11 SDK 附带 Swift 3.2(或 Swift 4),因此您可以使用 Swift 版本检查来完成同样的事情:
#if swift(>=3.2)
if #available(iOS 11.0, *) {
…
}
#endif
这是Apple建议的解决方案:
if #available(iOS 11.0, *) {
// iOS 11 specific stuff here
} else {
// non iOS 11 stuff here
}
请参考this resource(更多详情请观看标记6:50上的视频)
我明白了。我有一个旧的 Mac 我喜欢使用它,它对 Xcode 9 来说太旧了,所以我希望有时也能够在 Xcode 8 下编译我的项目。
但是如果你只想支持 iOS 10 和 iOS 11,简单的方法是将 Xcode 目标的最低 SDK 设置为 10.0,并且始终使用 iOS 11 SDK 进行编译。 Swift 在这种情况下会为你工作,并给你语法错误,除非你正确使用 if #available(iOS 11.0, *) {
您仍然可以在 iOS 10 和 iOS 11 下进行测试,而无需为 Xcode 8 操心。
从Xcode8的角度来看,你是在试图从未来编译源代码。 Xcode 8.
没有好的解决方案展望未来,这里是解决方案:
在Xcode9.3(Swift4.1)中,你可以说:
#if canImport(MagiciOS12Kit)
if #available(iOS 12.0, *) {
MagiciOS12Class.standard.method()
}
#endif
并且您的代码仍将在 Xcode 9.3 下编译,但会跳过未来需要假设的 Xcode 10.0 或更高版本的内容。
#if canImport(moduleName) 仅在 Swift 4.1 中添加,Xcode 8 无法处理。但即便如此,这也仅适用于 Apple 未来添加的整个模块。如果 Apple 只是用新方法扩展现有的 class,就像在你的 navigationController.navigationBar.prefersLargeTitles 中一样,你仍然无法测试 prefersLargeTitles,但是你可以找到苹果与 prefersLargeTitles 同时引入的另一个框架,并使用 #if canImport(... ).
如果你想把条件放在函数之外,你可以像下面那样做。
@available(iOS 11.0, *)
func functionName() {
// function contents
}
你可以实现,像下面这样的功能
@available(iOS 11.0, *)
func myFunction() {
// function defination
}
或者如果你想检查内部函数写这个
if #available(iOS 11.0, *) {
// iOS 11 specific stuff here
} else if #available(iOS 10.0, *) {
// iOS 10 specific stuff here
} else {
// non iOS 11 & 10 stuff here
}