为什么objective-c没有API可用性检查?

为什么objective-c没有API可用性检查?,objective-c,llvm-clang,Objective C,Llvm Clang,Swift 2有API 当使用对您的应用程序来说太新的API时,编译器会给您一个错误 最小目标操作系统 为什么objective-c编译器不能做同样的事情 我在谷歌上搜索了objective c API可用性检查,只得到了swift 2的结果,所以我假设objective c的编译器不能这样做。当然,objective-c代码中会出现错误。但是,如果您使用为Swift定义的术语,您将无法在google中找到Objective-C的结果,因为如果您搜索德语单词,您将无法在google中找到kisu

Swift 2有API

当使用对您的应用程序来说太新的API时,编译器会给您一个错误 最小目标操作系统

为什么objective-c编译器不能做同样的事情


我在谷歌上搜索了objective c API可用性检查,只得到了swift 2的结果,所以我假设objective c的编译器不能这样做。

当然,objective-c代码中会出现错误。但是,如果您使用为Swift定义的术语,您将无法在google中找到Objective-C的结果,因为如果您搜索德语单词,您将无法在google中找到kisuaheli网站。;-)

将Objective-C代码与太旧的SDK链接时会出现错误。这仅仅是因为所使用的方法、类或$which没有在该SDK的头中定义。当然,也是这样

这就是苹果公司典型的Swift营销:由于Swift的无能力,他们必须扩展语言才能获得一些东西,这在Objective-C中非常容易。他们没有澄清这是Swift的糟糕表现的结果,而是告诉你这是Swift的一个重要特征。这就像割断你的手指,然后说:“我们有伟大的石膏功能!!!!!!!”你只需要等待几天,然后一个问题出现了:“为什么Objective-C没有伟大的石膏功能?”简单的回答是:它不会割断你的手指

问题不在于产生错误。问题是所有版本都有一个源代码,因此您可以简单地更改SDK版本并获取新代码(或错误)。为了便于维护,您需要它

在Objective-C中,您只需使用以下答案: 或者你也可以在运行时这样做,正如Q的注释中所提到的。(但这本质上是问题的不同解决方案,因为它是一种动态的方法,而不是Swift中必须使用的静态方法。)

在Swift中具有语言功能的原因是Swift没有预处理器,因此Objective-C解决方案在Swift中不起作用。因此,条件代码在Swift中是不可能的,他们必须添加Plast,呃,语言功能。

警告(Swift使其成为错误)已经多年没有在Clang编译器中实现,但它不是固有的Objective-C限制(尽管由于其动态特性,您无法捕获所有情况),也不是快速的术语

苹果的宏(例如,
NS\u CLASS\u AVAILABLE
)和源属性(
\uuu attribute\uuuuuuuuuu((可见性(…)))
\uuuuu attribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu((可用性(…)))
)已经存在多年,它们在苹果的SDK中被广泛使用。宏在
Foundation
NSObjCRuntime.h
Availability.h
/
AvailabilityMacros.h
系统头中定义,编译器可以(并且确实)读取宏

2015年初,向Clang的
master
分支发出的
-Wpartial availability
警告,但直到(包括)Xcode 7.2,该提交/警告才进入苹果的Clang版本。在Xcode 7.2中将警告标志添加到项目时,您将获得一个
未知警告选项
日志,但该标志在Xcode 7.3中可用。当前没有预定义的设置,但您可以将该标志添加到“生成设置”下的“其他警告标志”

还有其他工具使用LLVM库来检测部分可用的API,例如。在我的毕业论文中,我开发了一个直接集成到Xcode的工具,它基于对Clang编译器的修改。代码仍然是,但是我没有跟上一般的Clang开发,所以除了用于学习之外,它没有多大用处。然而,“官方”代码(如上链接)更干净、更好


编辑:从Xcode 9开始,可用性检查也适用于Objective-C(和C)。不使用上述警告标志(不支持临时/本地提升部署目标,因此会导致大量误报),而是使用
-Wunguarded availability
,和
if(@available(iOS 11,*){…}
检查并提升部署目标以获取以下代码块。默认情况下,它是关闭的,但默认情况下,Wunguarded availability new将打开,并开始检查iOS/tvOS 11、watchOS 4和High Sierra之外的任何内容。有关这方面的更多详细信息,请参见,目前需要使用开发人员帐户登录。

目标C没有可用性检查作为语言的一部分,因为通过目标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操作系统版本,例如:

#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:,或InstanceRespondsToSelector:(后者在类级别)

您通常希望将这两种方法结合起来,即编译时条件编译和运行时检查

目标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


不能在两种语言中使用相同的方法。

Xcode 9.0将运行时可用性检查语法从Swift引入Objective-C:

if (@available(macOS 10.9, *))
{
// call 10.9+ API
}
else
{
// fallback code
}
这完全是w