Interacting with Passes in Your App
There are two main reasons apps interact with passes: to provide an integrated user experience or to serve as a conduit for passes. An event venue’s app is an example of an integrated user experience. This app can show the performance schedule, play short video clips, and let users buy tickets. After buying a ticket, it can add a pass for that ticket to Wallet and create an event in the user’s calendar. It can also include UI for managing the tickets that users have purchased. An email or instant messaging client is an example of an app serving as a conduit. Just as it supports attachments such as images, it can also support passes attached to a message like Mail does. The app can display UI that indicates that the message has a pass attached and allow users to add the pass to their library. Supporting passes in your app should add value for the user; avoid trying to duplicate functionality of the Wallet app.
Enabling Passbook Capabilities
Your app must have the appropriate entitlements before it can read, update, or delete passes. Use the Xcode Capabilities tab to turn on entitlements. If your provisioning profile is associated with multiple pass type identifiers, you can specify which of the identifiers your app can interact with. For more information, see Configuring Passbook for iOS Apps.
The PassKit framework provides model-level access to pass data. The
PKPassLibrary class represents the pass library, and the
PKPass class represents individual passes. The framework also provides a view controller, the
PKAddPassesViewController class, which displays a pass and lets users add it to their pass library. Your app is responsible for the views it needs to display passes. To present a pass, use the
passURL property of a pass to show it in Wallet.
[[UIApplication sharedApplication] openURL:[pass passURL]]
A pass should not depend on your app to be useful. Passes need to be self-contained and useful by themselves, even if your app is not installed.
Checking Whether the Pass Library Is Available
The presence of the PassKit framework and its classes doesn’t mean that the pass library is available. To check for its availability, call the
isPassLibraryAvailable method of the
Checking Whether a Pass Is in the Library
You can determine whether a pass is in the library even if you don’t have the entitlement to read the pass. This feature allows apps to act as a conduit for passes that they did not create. When you receive a new pass, check to see if it is in Wallet, and present the correct UI. If the pass is already in Wallet, indicate that the pass already exists. If the pass is not present, let users add it to Wallet.
To check whether a pass is in the library:
passes method of the
PKPassLibrary class to get all passes that your app is entitled to access. Passes are returned in an arbitrary order. If your app displays a list of passes, it should sort them in some meaningful way such as by date.
To receive notifications when the pass library changes, register for the
PKPassLibraryDidChangeNotification notification. Pass the instance of
PKPassLibrary as the object. The pass library isn’t a singleton; each instance sends its own notifications, and you want the notifications from this particular instance. Use the
addObserverForName:object:queue:usingBlock: method to specify that you want to respond on the main queue and provide a block to handle the notification. The user info dictionary of the notification describes what changed. Alternatively, use the
dispatch_get_main_queue functions to respond on the main thread.
Reading a Pass
passWithPassTypeIdentifier:serialNumber: method of the
PKPassLibrary class to read a particular pass from the pass library.
You can access certain common bits of data, such as the organization name and description, using the properties of the
PKPass class. You can access the description using the
localizedDescription method. These properties are useful if your app is acting as a conduit passes that you didn’t create, so you don’t know their fields’ keys.
You can access specific fields of a pass using the their key with the
localizedValueForFieldKey: method. This method is useful if you created the pass, because then you know the keys for specific fields.
Adding a New Pass
To add a pass to the library:
Create an instance of the
PKPassclass for the pass, initializing it with the pass’s data.
containsPass:method of the
PKPassLibraryclass to check whether the pass is in the library. Your app can use this method to detect the presence of a pass even if it doesn’t have the entitlements to read passes in the library.
If the pass isn’t in the library, use an instance of the
PKAddPassesViewControllerclass to let the user add it.
Present the add passes view controller modally, with animation.
Changing a Pass
Passes cannot be changed directly on the device. Changing the contents of a pass would invalidate its signature. An updated pass needs to be signed using your private key, and distributing your private key as part of your app would be a particularly poor security practice.
To change a pass, coordinate with your server:
Your app connects to your server. It identifies the pass by serial number and pass type identifier and describes the change to your server.
Your server updates your business records as needed, creates a new version of the pass, and signs it.
Your app downloads the new pass from your server and uses the
replacePassWithPass:method of the
PKPassLibraryclass to install it.
After creating a new version of the pass, your server should also send a push notification so that other devices with this pass installed will get the latest copy.
Removing a Pass
removePass: method of the
PKPassLibrary class to remove a pass.
Remember that passes belong to the user, not to your app. Passes should be removed only in response to a direct user action. Never remove a pass without the user’s consent, even if the pass has expired or is outdated.