如何将@available用于已重命名的方法



PushKit在iOS 11中有一个新方法,旨在取代iOS 10中的方法。

使用 iOS 11 作为基本 SDK 进行构建时,无法使用 iOS 11 方法(我目前使用的是 Xcode 9.2B),因为有一个编译器错误,指出该方法已重命名。但也无法使用iOS 11方法,然后在iOS 10设备上运行该应用程序,因为会出现无法识别的选择器异常。

我不能使用 #available{}else{},因为它是一个完整的方法。

所以我这样做了

@available(iOS, introduced: 8.0, deprecated: 11.0)
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType)
{
 ...   
}
@available(iOS 11.0, *)
public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Swift.Void)
{
    ...
}

或:

@available(iOS 11, *)
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void)
{
...
@available(iOS 10, *)
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType)
{
...

但这两种情况都会导致第二个声明出现编译错误,指出它已被重命名。

如何使用 iOS 11 或 iOS 10 版本?

(该应用程序不支持版本 <10)

这里的部分问题是 Swift 3 和 Swift 4 之间的差异,以及 iOS 11 中一个委托方法的附加参数。

以下代码使用 iOS 10 的部署目标和 iOS 11.1 的基本 SDK 在 Swift 3.2 中进行了干净的编译:

import UIKit
import PushKit
class ViewController: UIViewController, PKPushRegistryDelegate {
    func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, forType type: PKPushType) {
    }
    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
        pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type) {
            // no-op
        }
    }
    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
        // Do what is needed
        completion()
    }
}

下面的编译使用 Swift 4 进行了干净的编译:

import UIKit
import PushKit
class ViewController: UIViewController, PKPushRegistryDelegate {
    func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
    }
    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
        pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type) {
            // no-op
        }
    }
    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
        // Do what is needed
        completion()
    }
}

这两组代码之间的唯一区别是,在 Swift 3 下,前两个方法有一个名为 forType 的参数,而在 Swift4 下,它被命名为 for

新的 iOS 11 API 使用 for 作为该参数,而不管 Swift 版本如何。

现在剩下的问题是,你是否真的需要提供前两个委托方法的两个副本,一个集合包含 for,另一个集合包含 forType,以确保所有委托方法实际上都在所有 iOS 版本下调用,无论您使用哪个 Swift 版本?

最新更新