How to implement PKPaymentAuthorizationViewControllerDelegate in Xcode 9 for iOS 8 backward compatibility?

I am trying to create an application using Apple Pay on Xcode 9. The deployment target is iOS 8.

Until Xcode 8.3.3 (and iOS 10 SDK) works fine:

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 } 

Now, with Xcode 9, I get the following build error:

Protocol "PKPaymentAuthorizationViewControllerDelegate" requires "paymentAuthorizationViewController (_: didSelectShippingContact: completion :)", which will be available on iOS 8.0 and later

This means that I have to change @available(iOS 9, *) to @available(iOS 8, *) .

Looking at the definition of PKPaymentAuthorizationViewControllerDelegate , I see the following:

 @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) 

Thus, the method is determined to be available from iOS 8.

Here comes the catch: in the PKContact definition (which is part of the method signature of the specified method), you can see the following:

 @available(iOS 9.0, *) open class PKContact : NSObject { ... } 

So, according to the current SDK, the method is available on iOS 8 (which leads to a build error), but one of its parameter types is available only on iOS 9. This seems to be mutually exclusive.

I know that the method I'm trying to implement is deprecated, but replacement is only available on iOS 11, so now it seems that I need to implement deprecated methods anyway (or am I mistaken here?).

Does anyone have the same problem? Any thoughts on this? I appreciate every thought :)

Thanks!

+5
source share
1 answer

Protocol "PKPaymentAuthorizationViewControllerDelegate" requires' PaymentAuthorizationViewController (_: didSelectShippingContact: completion :) for access to iOS 8.0 and later

does not mean that this method requires iOS 8.0 and newer. This means that this method is released in the class, which should support iOS 8.0. You can easily verify this by putting @available(iOS 9.0, *) before the class declaration

 @available(iOS 9.0, *) class MyViewController: UIViewController, PKPaymentAuthorizationViewControllerDelegate { //... } 

the error will disappear

But how to deal with your problem. Create two classes from which the PKPaymentAuthorizationViewControllerDelegate protocol will be released. One of them should release support for iOS 8, and the other - iOS 9 and a new one.

 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 } } 

Now you can use the appropriate class in accordance with the installed iOS

 if #available(iOS 9.0, *) { //use Payment } else { //use DeprecatedPayment } 

It will also be easy to give up support for legacy iOS when the time comes.

0
source

Source: https://habr.com/ru/post/1272117/


All Articles