How to create a StoreKit Coordinator in Swift

Oscar de la Hera Gomez
Three flowers that represent StoreKit, Swift & XCode. Beneath them sits the text "StoreKit Coordinator."

A step by step guide on setting up a StoreKit coordinator for managing the gathering, purchasing and verification of In-App Purchases and Subscriptions.

The following tutorial uses our Open Source Swift starter project to setup a StoreKit Coordinator for managing all events related to local or App Store Connect In-App Purchases and Subscriptions.

We recommend that you clone our Open Source Swift Starter Project, checking out the tutorial/storekit/setup branch and carrying out the steps below. The changes can be found on the tutorial/storekit/coordinator branch.

git clone git@github.com:delasign/swift-starter-project.git

Before you start

The StoreKitCoordinator manages the gathering, purchasing and verification of In-App Purchases and Subscriptions ("products") and works with a StoreKit Configuration File and a product offering (In-App Purchases & Subscriptions).

If you do not have a StoreKit Configuration File and product offering setup, please consult the tutorials below.

Please note that a sample StoreKit Configuration File and product offering are available as part of our Open Source Swift Starter Project on the tutorial/storekit/setup branch.

Once you have setup the StoreKit Configuration File and offering, you must enable StoreKit Testing.

If you do not you setup StoreKit Testing in XCode, you will encounter errors such as Finance Authorization Error, [StoreKit] Did not receive any products or error for products request, or No Active Account

Tutorial

Step One: Create the Offering Plist

A screenshot of XCode showing the Offering Plist with the keys set to the display names of our products and the keys to their respective product ids.

In the StoreKit folder under Models, create a new Property List file called Offering.plist.

In this file create a key value paring for each In-App Purchase or Subscription, with the key matching the Display Name and the value matching the product id of the respective In-App Purchase or Subscription.

Step Two: Create the Offering Configuration

A screenshot of XCode showing all the files and code produced in this step.

With the vision of avoiding typo's in strings and establishing a consistent pattern, we recommend that you create an Offering Configuration that gathers the Offering Plist and makes the identifiers available for consumption to the StoreKitCoordinator.

This is similar to the configuration file that we created for making Swift API calls.

A | Create the Offering Keys

A screenshot of XCode with the OfferingKeys.swift highlighted and showing the code available below.

Under Models, in the StoreKit folder, create a new file called OfferingKeys.swift and create enums that match your offering in a similar way to the code available below.

When writing your Enum, make sure that each of the cases matches an item in the Offering.plist that you created.

B | Create the Offering Configuration base file

A screenshot of XCode with the OfferingConfiguration.swift highlighted and selected, showing the code available below.

Under Models, in the StoreKit folder, create a new file called OfferingConfiguration.swift and paste in the code below.

This file is responsible for gathering the offering on initialization and allocating it to an offering variable so that it can be consumed by the StoreKitCoordinator. It also carries a utility to access the value (i.e. product id) when passing in a key (which matches one of the enums created in the step above).

C | Create the Offering Configuration Get functionality

A screenshot of XCode with the OfferingConfiguration+Get.swift highlighted and selected, showing the code available below.

Under Models, in the StoreKit folder, create a new file called OfferingConfiguration+Get.swift and paste in the code below.

This file is responsible for offering functions that return the value (i.e. product id) for an In-App Purchase or Subscription within your offering.

Step Three: Create additional Models & Utilities

A screenshot of XCode showing the files created for the additional models and utilities.

This step involves creating the typealias StoreKit utility as well as the StoreKit error and Subscription Tiers models.

A | Typealias Utility

A screenshot of XCode showing the Typealiases created for the StoreKit Coordinator.

In the Utils folder, create a folder called StoreKit and within it, create a file called StoreKitTypeAliases.swift and copy in the code below.

B | Error Model

A screenshot of XCode showing the StoreKit errors. Code available below.

Under Models, in the StoreKit folder, create a new file called StoreKitError.swift and paste in the code below.

C | Subscription Tier Model (Optional)

A screenshot of XCode showing the Subscription Tiers model. Code available below.

This step is only required if your App uses one or more Subscription Groups which have multiple levels of service.

Under Models, in the StoreKit folder, create a new file called SubscriptionTiers.swift and define the levels of service for your subscriptions using code similar to that below.

In contrast to the Subscription Levels defined in your Subscription Group, which appear in descending order, the Subscription Tiers in this file must be written in ascending order.

Please note that we have created a sample for a two tier subscription service within a single Subscription Group. You should code this to the requirements of your business logic, which may require more than one file for Subscription Tiers if you use multiple Subscription Groups.

Step Four: Create the Coordinator

A screenshot of XCode showing the StoreKit Coordinator files. All the code for the files is available below.

The StoreKitCoordinator has been broken down into a series of files to help breakdown all the required functionality and is based on Apple's Open Source StoreKit Project which was demonstrated in Meet StoreKit 2 (WWDC21). Both of these are available in below.

Please note that we have not included functionality for the handling of consumables in this tutorial.

A | Create the folder

A screenshot of Xcode showing the StoreKitCoordinator folder under Coordinators.

Under the Coordinators folder, create a new folder called StoreKitCoordinator.

B | Create base file

A screenshot of XCode showing the StoreKitCoordinator base file. Code available below.

In the StoreKitCoordinator folder create a new file called StoreKitCoordinator.swift and copy in the code below.

Please note that the StoreCoordinator includes variables for individual arrays, each of which holds items using known In-App Purchase or Subscription names.

This should be updated to suit the business logic of your app.

For an example of how to do this, consult Meet StoreKit 2 (WWDC21).

Additionally, the variables include a status which is written to, to manage the status of a single subscription group. You should include more statuses if you are using multiple subscription groups.

C | Create the Listener functionality

A screenshot of XCode showing the StoreKitCoordinator Listener extension. Code available below.

In the StoreKitCoordinator folder create a new file called StoreKitCoordinator+Listener.swift and copy in the code below.

This functionality is responsible for listening for updates on App Store Connect or a local StoreKit file, which could occur on devices separate from the one you're on (i.e. if a family member upgrades to a family plan or when a guardian or bank approves a pending purchase, the app will listen for that update and automatically update your availability).

D | Create the Get functionality

A screenshot of XCode showing the StoreKitCoordinator Get products extension. Code available below.

In the StoreKitCoordinator folder create a new file called StoreKitCoordinator+Get.swift and copy in the code below.

This functionality is responsible for gathering the products from the StoreKit Configuration File.

E | Create the Purchase functionality

A screenshot of XCode showing the StoreKitCoordinator Purchase products extension. Code available below.

In the StoreKitCoordinator folder create a new file called StoreKitCoordinator+Purchase.swift and copy in the code below.

This functionality is responsible for handling the purchase of products.

F | Create the Verify functionality

A screenshot of XCode showing the StoreKitCoordinator Verify products extension. Code available below.

In the StoreKitCoordinator folder create a new file called StoreKitCoordinator+Verify.swift and copy in the code below.

This functionality is responsible for determining if a product has been purchased as well as to verify the purchase of products.

H | Create the Update functionality

A screenshot of XCode showing the StoreKitCoordinator Update products extension. Code available below.

In the StoreKitCoordinator folder create a new file called StoreKitCoordinator+Update.swift and copy in the code below.

This functionality is responsible for running through and verifying the products that a customer is entitled to and adding them to the relevant purchased array.

Step Five: Initialize StoreCoordinator

A screenshot of XCode showing how we initialized the StoreKitCoordinator.

In the ViewController.swift file, in the setupCoordinator function, initialize the StoreCoordinator.

StoreKitCoordinator.shared.initialize()

Step Six: Create the StoreKit Notifications

A screenshot of Xcode showing the SystemNotifications.swift file with the new notifications which are offered to you in a code snippet below.

Under Models/Notifications in the SystemNotifications.swift file, add the three notifications available in the snippet below.

These are responsible for notifying the app of:

  • StoreKit Updates - this notification is recommended to be used at the end of the +Update extension, which gets triggered when the StoreKitCoordinator initializes and every time the transaction listener receives an update.
  • StoreKit Product Updates - this notification is recommended to be used in the +Purchase extension, to notify the system of specific product purchases. We recommend including the product and the type of result within the notification, to ensure that the right actions get taken, depending on the product and result.
  • StoreKit Refund Updates - this notification is recommended to be used to notify the system of a refund state update and is recommended to include the product as well as a refund result (success, pending, failed, cancelled) to make sure that the right actions get taken in your app.

Step Seven: Notify System of StoreKit Update

A screenshot of the StoreKitCoordinator+Update.swift extension. Highlighted is the onStoreKitUpdate notification, which is sent at the end of the file.

In the StoreKitCoordinator+Update.swift file that you created in Step Four, Part H; send the onStoreKitUpdate notification that you created in Step Six at the end of the process.

NotificationCenter.default.post(name: SystemNotifications.onStoreKitUpdate, object: nil)

Step Eight: Trigger updates when returning to the foreground

A screenshot of the files and changes that are carried out in this set to setup a notification observer that gets triggered when the app returns to the foreground. When this is triggered, we ask the StoreKitCoordinator to updateCustomerProductStatus.

As expired Subscriptions do not trigger an update to the StoreKit Coordinator's transaction listener, we recommend that you trigger an updateCustomerProductStatus when the App returns to the foreground.

The only way to receive real-time updates and take action on these events is to use App Store Server Notifications.

A | Create ViewController Notification extension

A screenshot of Xcode showing the ViewController+Notifications.swift file that is created in this step. Code below.

Under RootViewController create a new file called ViewController+Notifications.swift and paste in the code below. This code is responsible for setting up the notifications for when the app enters the foreground and triggering the updateCustomerProductStatus.

B | Call Setup Notifications

A screenshot of Xcode showing the ViewController.swift file. Highlighted is setupNotifications() in the viewDidLoad lifecycle function.

In ViewController.swift in the viewDidLoad function, call setupNotifications().

Step Nine: Verify

A screenshot of XCode showing the logs that describe that the StoreKitCoordinator was initialized successfully and that it gathered all the In-App Purchases and Subscriptions from the StoreKit Configuration File.

Run your project and using the debug console you will see that logs show that the products have been gathered successfully.

If you happen to run into an error, such as Finance Authorization Error, [StoreKit] Did not receive any products or error for products request, or No Active Account, make sure that XCode has been setup for StoreKit testing.

Looking to learn more about developing apps with StoreKit 2?

Read our comprehensive development guide linked below to learn about all the secrets behind developing In-App Purchases and Subscriptions with StoreKit 2.

Any Questions ?

We are actively looking for feedback on how to improve this resource. Please send us a note to inquiries@delasign.com with any thoughts or feedback you may have.
delasign logo

Book a Free Consultation.

An icon of an email.

Click here to email us.

Fill in the details below to book a free consultation or to let us know about something else. Whatever it is, we are here to help.

How can we help you ?

Contact Details