如何在Xcode 9中实现PKPaymentAuthorizationViewControllerDelegate for iOS 8向后兼容性?

flo*_*ger 5 xcode passkit swift applepay xcode9

我正在尝试构建一个在Xcode 9上使用Apple Pay的应用程序.部署目标是iOS 8.

直到Xcode 8.3.3(和iOS 10 SDK),这完美地运作:

extension MyViewController: PKPaymentAuthorizationViewControllerDelegate {

func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingAddress address: ABRecord, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Void) {
    // handle the ABRecord for iOS 8
}

@available(iOS 9.0, *)
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingContact contact: PKContact, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Void) {
    // handle the PKContact on iOS 9 and later
}
Run Code Online (Sandbox Code Playgroud)

现在,使用Xcode 9,我得到以下构建错误:

协议'PKPaymentAuthorizationViewControllerDelegate'要求'paymentAuthorizationViewController(_:didSelectShippingContact:completion :)'在iOS 8.0及更高版本上可用

这意味着,我应该改变@available(iOS 9, *)@available(iOS 8, *).

查看PKPaymentAuthorizationViewControllerDelegate我的定义,我看到以下内容:

@available(iOS, introduced: 8.0, deprecated: 11.0, message: "Use paymentAuthorizationViewController:didSelectShippingContact:handler: instead to provide more granular errors")
optional public func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingContact contact: PKContact, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Swift.Void)
Run Code Online (Sandbox Code Playgroud)

因此,该方法被定义为可从iOS 8开始使用.

PKContact接下来是:查看(上面方法的方法签名的一部分)的定义,您可以看到以下内容:

@available(iOS 9.0, *)
open class PKContact : NSObject {
    ...
}
Run Code Online (Sandbox Code Playgroud)

因此,根据当前的SDK,该方法在iOS 8上可用(导致构建错误),但其中一个参数类型仅在iOS 9上可用.这似乎是互斥的.

我知道我试图实现的方法已被弃用,但替代版仅在iOS 11上可用,所以现在我似乎需要实现已弃用的方法(或者我在这里错了?).

有没有人有同样的问题?有什么想法吗?我很欣赏每一个想法:)

谢谢!

Tar*_*nko 0

协议“PKPaymentAuthorizationViewControllerDelegate”要求“ paymentAuthorizationViewController(_:didSelectShippingContact:completion:)”在 iOS 8.0 及更高版本上可用

并不意味着该方法需要 iOS 8.0 及更高版本。这意味着该方法在类中发布的内容应该支持iOS 8.0。@available(iOS 9.0, *)您可以通过将其放在类声明之前轻松检查

@available(iOS 9.0, *)
class MyViewController: UIViewController, PKPaymentAuthorizationViewControllerDelegate {
    //...
}
Run Code Online (Sandbox Code Playgroud)

错误将会消失

但如何处理你的问题。创建两个将发布PKPaymentAuthorizationViewControllerDelegate协议的类。其中一个应该发布 iOS 8 支持,另一个应该发布 iOS 9 及新版本。

class DeprecatedPayment: NSObject, PKPaymentAuthorizationViewControllerDelegate {
    func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {

    }
    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingAddress address: AddressBook.ABRecord, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Swift.Void) {
    }
}

@available(iOS 9.0, *)
class Payment: NSObject, PKPaymentAuthorizationViewControllerDelegate {
    func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {
    }
    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingContact contact: PKContact, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Void) {
        // handle the PKContact on iOS 9 and later
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您将可以根据安装的iOS使用相应的类

if #available(iOS 9.0, *) {
    //use Payment
} else {
    //use DeprecatedPayment
}
Run Code Online (Sandbox Code Playgroud)

此外,当时机成熟时,很容易放弃对已弃用的 iOS 的支持。