检查Swift中是否有可用的功能?

时间:2014-11-03 02:24:17

标签: ios swift uiaccessibility

我想检测用户是否启用了“降低透明度”。很简单,您只需调用func UIAccessibilityIsReduceMotionEnabled()并返回Bool即可。但是我的应用程序针对的是iOS 7和8,并且这个功能在iOS 7上无法使用。

在Objective-C中,这是我检查该功能是否存在的方式:

if (UIAccessibilityIsReduceMotionEnabled != NULL) { }

在Swift中,我无法弄清楚如何检查它是否存在。根据{{​​3}},您可以简单地使用可选链接,如果它nil则它不存在,但显然仅限于Obj-C协议。 Xcode 6.1不是这样的:

let reduceMotionDetectionIsAvailable = UIAccessibilityIsReduceMotionEnabled?()

它要你删除?当然,如果你这样做,它将在iOS 7上崩溃,因为该功能不存在。

检查这些类型的函数是否存在的正确方法是什么?

4 个答案:

答案 0 :(得分:8)

Swift 2中添加了适当的可用性检查。建议使用此处提到的其他选项。

var shouldApplyMotionEffects = true
if #available(iOS 8.0, *) {
    shouldApplyMotionEffects = !UIAccessibilityIsReduceMotionEnabled()
}

答案 1 :(得分:5)

如果你有点厚颜无耻,你可以随时使用库加载器打开UIKit二进制文件,看看它是否可以解析符号:

let uikitbundle = NSBundle(forClass: UIView.self)
let uikit = dlopen(uikitbundle.executablePath!, RTLD_LAZY)
let handle = dlsym(uikit, "UIAccessibilityIsReduceMotionEnabled")
if handle == nil {
    println("Not available!")
} else {
    println("Available!")
}

dlopendlsym调用可能有点贵,但我建议在应用程序的生命周期中保持dlopen句柄处于打开状态并存储尝试{{{{ 1}}。如果不这样做,请确保dlsym

据我所知,这是AppStore的安全,因为dlclose是一个公共API。

答案 2 :(得分:2)

您可以查看您是否在iOS 8或更高版本中运行 -

var reduceMotionEnabled = false
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) {
    reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled()
}

我不认为还有另一种说法。所以从理论上讲,如果你能够检查,尝试访问没有()的函数名称会在iOS 7中提供nil,在iOS 8中提供() -> Bool函数。但是,在为了实现这一目标,UIAccessibilityIsReduceMotionEnabled需要定义为(() -> Bool)?,而不是let reduceMotionDetectionIsAvailable = UIAccessibilityIsReduceMotionEnabled // reduceMotionDetectionIsAvailable is now a () -> Bool reduceMotionDetectionIsAvailable() // crashes in iOS7, fine in iOS8 。测试它会在两个版本的iOS中产生一个函数实例,如果在iOS 7中调用它会崩溃:

// ObjC
static inline BOOL reduceMotionDetectionIsAvailable() {
    return (UIAccessibilityIsReduceMotionEnabled != NULL);
}

// Swift
var reduceMotionEnabled = false
if reduceMotionDetectionIsAvailable() {
    reduceMotionEnabled = UIAccessibilityIsReduceMotionEnabled()
}

我可以看到在没有测试版本的情况下执行此操作的唯一方法就是定义自己的C函数来检查桥接头文件,然后调用:

{{1}}

答案 3 :(得分:0)

来自Apple Developer docs(Using Swift with Cocoa and Objective-C (Swift 3) > Interoperability > Adopting Cocoa Design Patterns > API Availability):

  

Swift代码可以使用API​​的可用性作为条件   运行。可用性检查可用于代替a中的条件   控制流语句,例如ifguardwhile   言。

     

采用前面的示例,您可以检查if中的可用性   仅在方法时调用requestWhenInUseAuthorization()的语句   在运行时可用:

     
let locationManager = CLLocationManager()
if #available(iOS 8.0, macOS 10.10, *) {
    locationManager.requestWhenInUseAuthorization()
}
     

或者,您可以在guard声明中查看可用性,   除非当前目标满足,否则退出范围   规定的要求。这种方法简化了处理逻辑   不同的平台功能。

let locationManager = CLLocationManager()
guard #available(iOS 8.0, macOS 10.10, *) else { return }
locationManager.requestWhenInUseAuthorization()
     

每个平台参数由下面列出的平台名称之一组成,   后跟相应的版本号。最后一个论点是   星号(*),用于处理潜在的未来平台。

     

平台名称:

     
      
  • iOS
  •   
  • iOSApplicationExtension
  •   
  • macOS
  •   
  • macOSApplicationExtension
  •   
  • watchOS
  •   
  • watchOSApplicationExtension
  •   
  • tvOS
  •   
  • tvOSApplicationExtension
  •