ios - 如何对已重命名的方法使用@available?

标签 ios swift

PushKit 在 iOS 11 中提供了一种新方法,旨在取代 iOS 10 中的方法。

使用 iOS 11 作为基础 SDK 构建时无法使用 iOS 10 方法(我当前使用的是 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 中单一委托(delegate)方法的附加参数。

以下代码使用 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 版本如何。

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

关于ios - 如何对已重命名的方法使用@available?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47066833/

相关文章:

ios - 应用内购买在发布近一周后仍无法正常工作

ios - exc_arithmetic 错误仅与模拟器,分配 UICollectionView flowlayout

ios - 使用 Web 服务时 Swift 中的错误代码=-1005 "The network connection was lost."

ios - Swift - 将值从线程保存到变量

ios - .AllowUserInteraction 不适用于 UIImageView

ios - 无法安装分发配置文件

ios - 如何在 iOS 上恢复蓝牙连接

ios - 如何在 ios 中对 Storyboard中的一组元素使用约束?

ios - 如何在 Swift 中删除属于同一对象的所有对象

IOS/ARKIT - 如何做上一个和下一个按钮,点击时用动画改变 3D 模型?