Swift 2有API availability checking。
当使用对您来说太新的API时,编译器会给您一个错误 最低目标操作系统
为什么objective-c编译器不能做等效的?
我搜索了目标c API可用性检查,只有swift 2结果出来,所以我假设目标c的编译器不能这样做。
答案 0 :(得分:44)
Xcode 9.0将运行时可用性检查语法从Swift带到Objective-C:
if (@available(macOS 10.9, *))
{
// call 10.9+ API
}
else
{
// fallback code
}
这有完整的警告,用于调用比部署目标更新的API(如果这些调用未包含在检查中)。
最后;)
答案 1 :(得分:20)
警告(Swift使其成为错误)多年来一直没有在Clang编译器中实现,但它不是固有的Objective-C限制(尽管由于它的动态特性,你赢了& #39;能够捕捉所有案例),也不能赶上Swift术语。
用于注释带有可用性信息的标头的Apple宏(例如,NS_CLASS_AVAILABLE
)和源属性(__attribute__((visibility(...)))
,__attribute__((availability(...)))
)已存在多年,并广泛用于Apple的SDK。这些宏在Foundation
' NSObjCRuntime.h
和Availability.h
/ AvailabilityMacros.h
系统标头中定义,编译器可以(并且确实)读取它们。
2015年初,对{@}} -Wpartial-availability
分支master
警告has been added,但此提交/警告未进入Apple'版本的Clang直到(包括)Xcode 7.2。在Xcode 7.2中向项目添加警告标志时,您将获得unknown warning option
日志,但该标志在Xcode 7.3中可用。目前没有预定义设置,但您可以在构建设置下将标记添加到Other Warning Flags
。
还有其他工具使用LLVM库来检测部分可用的API,例如Deploymate。对于我的毕业论文,我开发了一个直接集成到Xcode中的工具,它基于对Clang编译器的修改。代码仍然是online,但我还没有跟上Clang的一般开发,因此除了学习目的外,它不会有多大用处。然而,"官方"代码(上面链接的)更清洁,更好。
编辑:从Xcode 9开始,可用性检查也适用于Objective-C(和C)。而不是使用上述警告标志,它不支持临时/本地提升部署目标,因此导致大量误报,而-Wunguarded-availability
和if (@available(iOS 11, *)) {...}
检查和提升以下代码块的部署目标。它默认是关闭的,但默认情况下会-Wunguarded-availability-new
处于启用状态,并开始检查iOS / tvOS 11,watchOS 4和High Sierra之外的任何内容。有关详细信息,请参阅Xcode 9 beta release notes,目前需要使用开发者帐户登录。
答案 2 :(得分:3)
目标C没有可用性检查作为语言的一部分,因为可以通过Objective C预处理器获得相同的结果。 这就是"传统"用C语言编写的方法。
想知道是否在调试模式下编译?
#ifdef DEBUG
// code which will be inserted only if compiled in debug mode
#endif
想在编译时检查最低版本吗? 使用iOS中的Availability.h标头和Mac OS X的类似标头。
此文件位于/ usr / include目录中。
只需使用预处理器测试__IPHONE_OS_VERSION_MAX_ALLOWED,例如:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil]];
}else{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)];
}
#else
[[UIApplication sharedApplication] registerUserNotificationSettings: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)];
#endif
由于Swift没有预处理器,他们必须发明一种在语言本身内进行这种检查的方法。
如果要在运行时检查方法的可用性,请注意适当的方法是使用方法 respondsToSelector:,或 instancesRespondToSelector:(后者在班级)。
您通常希望将两种方法结合起来,编译时条件编译和运行时检查。
目标C方法存在验证,例如在班级:
if ([UIImagePickerController instancesRespondToSelector:
@selector (availableCaptureModesForCameraDevice:)]) {
// Method is available for use.
// Your code can check if video capture is available and,
// if it is, offer that option.
} else {
// Method is not available.
// Alternate code to use only still image capture.
}
如果你想测试运行时是否存在C函数,它甚至更简单:如果存在,函数本身就不是null。
您无法在两种语言中使用相同的相同方法。
答案 3 :(得分:1)
答案 4 :(得分:-3)
当然,您将在Objective-C代码中遇到错误。但是如果你使用为Swift定义的术语,你将不会在Google中找到Objective-C的结果,因为如果你搜索德语单词,你将无法在google中找到kisuaheli网站。 ; - )
将Objective-C代码与过旧的SDK相关联时会出错。这只是因为使用的方法或类或$ SDK的标头中没有定义。当然,再次。
这是Apple的典型Swift营销:因为Swift无法扩展语言以获得某些东西,这在Objective-C中非常容易。他们告诉你这是Swift的一个很棒的功能,而不是澄清这是Swift的不良结果。这就像割你的手指然后说:“我们有很棒的石膏功能!!!!!!!!”你只需要等待几天,然后就可以通过问:“为什么Objective-C没有伟大的石膏功能?”简单的答案:它不会割伤你的手指。
问题是不生成错误。问题是为所有版本提供一个源代码,因此您只需更改SDK版本并获取新代码(或错误)。您需要这样才能更容易维护。
在Objective-C中你可以使用这里找到的答案: Conditionally Hide Code from the Compiler或者您可以在运行时按照Q的注释中的说明执行此操作。(但这本质上是问题的不同解决方案,因为它是一种动态方法而不是静态方法,因为您必须在迅速的。)
在Swift中使用语言功能的原因是Swift没有预处理器,所以Objective-C解决方案在Swift中不起作用。因此,Swift中的条件代码是不可能的,他们必须添加石膏,呃,语言功能。