Swift:iOS 部署目标命令行标志
Posted
技术标签:
【中文标题】Swift:iOS 部署目标命令行标志【英文标题】:Swift: iOS Deployment Target Command Line Flag 【发布时间】:2014-08-13 16:34:55 【问题描述】:如何在 Swift 条件编译语句中检查 ios 部署目标?
我尝试了以下方法:
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
// some code here
#else
// other code here
#endif
但是,第一个表达式导致编译错误:
Expected '&&' or '||' expression
【问题讨论】:
***.com/questions/24003291/… @VincentGuerci 谢谢。我看到了,但它没有回答我的(更具体的)问题。 您需要的一切都在此链接中,尤其是在苹果文档中,我认为没有内置的__IPHONE_OS_VERSION_MIN_REQUIRED
或类似的可用(还没有?),但您可以使用自己的构建配置变量。或者可能使用通过 .h 标头导入到 swift 中的“简单宏”来欺骗。
@VincentGuerci 是的,__IPHONE_OS_VERSION_MIN_REQUIRED
是内置的。如果您在 Xcode 中将它输入到您的 .swift
文件之一并单击它,Xcode 会将您带到它的声明:var __IPHONE_OS_VERSION_MIN_REQUIRED: CInt get
。我不想指定多余的命令行标志。我想使用内置的,这样当我将 Xcode 中的 iOS 部署目标更改为 iOS 8(及更高版本)时,Xcode 可以正确编译我的代码。
我刚看到your answer。谢谢,详尽的解释。我现在只注释掉我的 iOS 8 代码。然后,一旦 Apple 公开发布 iOS 8,我将停止支持 iOS
【参考方案1】:
TL;博士? > 转到 3。解决方案
1。 Swift 中的预处理
根据Apple documentation on preprocessing directives:
Swift 编译器不包含预处理器。相反,它需要 编译时属性、构建配置和 语言特性来完成相同的功能。为了这 原因是 Swift 中没有导入预处理器指令。
这就是为什么您在尝试使用 __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
(这是一个 C 预处理指令)时出错的原因。使用 swift 您不能将#if
与<
等运算符一起使用。你所能做的就是:
#if [build configuration]
或带条件:
#if [build configuration] && ![build configuration]
2。条件编译
再次来自the same documentation:
构建配置包括文字 true 和 false 值, 命令行标志,以及在 下表。您可以使用 -D 指定命令行标志。
true
和 false
:帮不了我们
平台测试功能:os(iOS)
或arch(arm64)
> 对您没有帮助,搜索了一下,无法确定它们的定义位置。 (可能在编译器本身?)
命令行标志:开始吧,这是您可以使用的唯一选项...
3。解决方案
感觉有点像一种解决方法,但确实有效:
现在例如,您可以使用#if iOSVersionMinRequired7
而不是__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0
,当然假设您的目标是iOS7。
这与在项目中更改 iOS 部署目标版本基本相同,只是不太方便... 当然,您可以根据您的 iOS 版本目标使用相关方案进行多重构建配置。
Apple 肯定会改进这一点,可能会使用一些内置功能,例如 os()
...
【讨论】:
现在有函数os()
和arch()
。 developer.apple.com/library/prerelease/ios/documentation/Swift/…【参考方案2】:
在 Swift 2.2 中测试
Deployment Target
是指iOS version
,还是App Target
?如果您有多个版本的应用程序(免费应用程序、付费应用程序......),下面我将提供解决方案,以便您使用不同的应用程序目标。
您可以设置自定义构建配置:
1. 转到您的项目/选择您的目标/构建设置/搜索自定义标志
2. 对于您选择的目标,使用 -D
前缀(不带空格)设置自定义标志,用于调试和发布
3. 为您拥有的每个目标执行上述步骤
要区分目标,您可以执行以下操作:
var target: String
var _target = ""
#if BANANA
_target = "Banana"
#elseif MELONA
_target = "Melona"
#else
_target = "Kiwi"
#endif
return _target
override func viewDidLoad()
super.viewDidLoad()
print("Hello, this is target: \(target)"
【讨论】:
我奇怪的好奇心。显然,这很有效,而且非常棒。谢谢!但是“-D”前缀有什么作用呢?它有什么用? @TheoBendixson 是告诉编译器后面的内容应该被视为自定义标志。例如,如果您想设置一个以“Og”开头的标志,无论出于何种原因,这都会被误解为试图同时传递“-O”和“-g”标志。 它也能在 Release 中工作吗? (D 不只是用于调试吗?) @RoiMulia True,D
与“调试”无关。它也适用于发布。【参考方案3】:
你不能在这样的条件编译语句中做到这一点。 Swift 不支持 Apple 所称的“复杂宏”。在他们看来,泛型和类型做同样的事情,结果更好。 (这是他们发布的链接https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_13)
这是我想出的一个函数,它完成了同样的事情(显然只需将字符串返回替换为对您有用的任何内容,例如布尔值或只是选项本身):
func checkVersion(ref : String) -> String
let sys = UIDevice.currentDevice().systemVersion
switch sys.compare(ref, options: NSStringCompareOptions.NumericSearch, range: nil, locale: nil)
case .OrderedAscending:
return ("\(ref) is greater than \(sys)")
case .OrderedDescending:
return ("\(ref) is less than \(sys)")
case .OrderedSame:
return ("\(ref) is the same as \(sys)")
// Usage
checkVersion("7.0") // Gives "7.0 is less than 8.0"
checkVersion("8.0") // Gives "8.0 is the same as 8.0"
checkVersion("8.2.5") // Gives "8.2.5 is greater than 8.0"
【讨论】:
谢谢,但这是一个 runtime 解决方案。我正在寻找一个 compile-time 解决方案。我现在只注释掉我的 iOS 8 代码。然后,一旦 Apple 公开发布 iOS 8,我将停止支持 iOS @MattDiPasquale 如果您有一个令人信服的编译时解决方案用例,您应该向 Apple 提交增强请求。你会帮助每个人的! @matt 我不记得为什么我想要一个编译时解决方案。也许我没有充分的理由,但基于my comment above,我想我在 iOS 8 仍处于测试阶段并希望能够更改 iOS 部署目标时为 iOS 8 编写代码已经超越了自己(在 Xcode 中指定)从 8 点到 7 点,然后将我的应用程序归档到 App Store。而且我想我不想创建一个新分支或让我的应用在不同版本的 iOS 上以不同的方式运行。【参考方案4】:我知道你的问题在这里已经有一段时间了,但万一有人还在寻找答案,他们应该知道从 Swift 2.0 开始你可以这样做:
if #available(iOS 8, *)
// iOS 8+ code
else
// older iOS code
您可以阅读更多关于它的信息here。
【讨论】:
这在运行时检查,但我的问题是如何在编译时检查。 我很确定,当您在“旧”括号中标记为从 iOS 8 开始可用的代码(如我给出的示例中)时,您无法编译它? 所以也许我'我并没有通过编译时间与运行时得到你的意思,但我想说这不是运行时检查? 没关系 :) 再想一想我明白你的意思 :P 太晚了 :) 长话短说:两个分支都必须编译和类型检查。 但是,我想这引发了一个问题:为什么你需要一个显式的编译时检查,而这很可能会奏效? ? 好问题。我试着在this comment回答。【参考方案5】:我最近在构建一个库时遇到了这个问题,该库的源代码支持具有不同功能的多个 iOS 和 macOS 版本。
我的解决方案是在 Xcode 中使用自定义构建标志,这些标志从实际部署目标中派生出它们的值:
TARGET_IOS_MAJOR = TARGET_IOS_MAJOR_$(IPHONEOS_DEPLOYMENT_TARGET:base)
TARGET_MACOS_MAJOR = TARGET_MACOS_MAJOR_$(MACOSX_DEPLOYMENT_TARGET:base)
参考 Others Swift Flags 中的那些用户定义设置,例如:
OTHER_SWIFT_FLAGS = -D$(TARGET_MACOS_MAJOR) -D$(TARGET_IOS_MAJOR)
允许我在我的 Swift 源代码中检查实际的主要操作系统版本,如下所示:
#if os(macOS)
#if TARGET_MACOS_MAJOR_12
#warning("TARGET_MACOS_MAJOR_12")
#elseif TARGET_MACOS_MAJOR_11
// use custom implementation
#warning("TARGET_MACOS_MAJOR_11")
#endif
#elseif os(iOS)
#if TARGET_IOS_MAJOR_15
#warning("TARGET_IOS_MAJOR_15")
#elseif TARGET_IOS_MAJOR_14
#warning("TARGET_IOS_MAJOR_14")
#else
#warning("older iOS")
#endif
#endif
目前我不知道在 SPM 包中是否可以使用类似的方法。这是我将在稍后阶段尝试做的事情。
【讨论】:
以上是关于Swift:iOS 部署目标命令行标志的主要内容,如果未能解决你的问题,请参考以下文章