斯威夫特#available关键字vs responsesToSelector [英] Swift #available keyword vs respondsToSelector

查看:127
本文介绍了斯威夫特#available关键字vs responsesToSelector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据

According to the pre-release Swift 2 documentation there is now an #available keyword that can be used with an if let or guard statement for checking API availability. It gives the following example:

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

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

(文档)所声明的内容等同于以下Objective-C代码:

Which it (the doc) states is the equivalent of the following Objective-C code:

if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {
  // Method is available for use.
} else {
  // Method is not available.
}

很明显,respondsToSelector:仅适用于NSObject的子类,而#available关键字甚至适用于纯" Swift代码,因此,我很欣赏这一优势.

Obviously respondsToSelector: only works on subclasses of NSObject whereas the #available keyword will work even for "pure" Swift code, so I appreciate that advantage.

但是,自从开始iOS开发以来,我一直被认为这种情况的最佳实践是检测API的存在,而不是依赖于其引入的版本.

However since starting iOS development I've always been led to believe that the best practice for this situation is to detect the presence of an API rather than rely on the version it was introduced.

作为一个更具体的示例,我在想苹果公司何时在iOS 7中的NSArray上引入了firstObject,但追溯地使其回到了iOS 4(可以使用但私有).任何使用respondsToSelector:的代码都可以在iOS<上运行. 7,但显然版本检查将失败.

As a more concrete example I'm thinking of when Apple introduced firstObject on NSArray in iOS 7 but retroactively made it available back to iOS 4 (where it was available, but private). Any code using respondsToSelector: would have worked on iOS < 7 but obviously a version check would fail.

转移到我错过的#available关键字是否有任何好处?

Are there any benefits to shifting to the #available keyword that I've missed?

推荐答案

一个很大的优点是Xcode 7中的Swift 2编译器比较了 类,方法,属性等的可用性对部署不利 项目的目标.

A big advantage is that the Swift 2 compiler in Xcode 7 compares the availability of classes, methods, properties, ... against the deployment target of your project.

使用respondsToSelector总是容易出错.对于Objective-C,

Using respondsToSelector was always error-prone. For Objective-C,

if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {

编译器仅验证requestWhenInUseAuthorization是否为 已知方法,但无法验证该检查在逻辑上是否正确.

the compiler only verifies if requestWhenInUseAuthorization is some known method, but it cannot verify if that check is logically correct.

在Swift中,情况更糟,因为只能将选择器指定为 字符串,并且编译器不验证任何内容.

In Swift it is even worse because selectors can only be specified as strings and the compiler does not verify anything.

使用Swift 2/Xcode 7,对应的代码

With Swift 2/Xcode 7, the corresponding code

let locationManager = CLLocationManager()
if locationManager.respondsToSelector("requestWhenInUseAuthorization") {
    locationManager.requestWhenInUseAuthorization()
}

如果部署目标小于iOS 8,

将不再编译 错误消息是

does not compile anymore if the deployment target is less than iOS 8, the error message is


error: 'requestWhenInUseAuthorization()' is only available on iOS 8.0 or newer
            locationManager.requestWhenInUseAuthorization()
                            ^
note: add 'if #available' version check

使用

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

编译器知道该方法仅在iOS 8及更高版本上被调用 并没有抱怨.

the compiler knows that the method will only be called on iOS 8 and later and does not complain.

这篇关于斯威夫特#available关键字vs responsesToSelector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆