StoreKit views APIs with iOS 17

Santosh Botre
5 min readJul 14, 2023

Display a customizable in-app purchase store using StoreKit views for SwiftUI.

Last article we discussed, How to implement and test In-App Purchase with StoreKit2 locally without AppStore Connect Account?

We are moving forward based on the insights provided in the last article without designing and implementing the in-app purchase product UI.

https://tenor.com/

New API Advancements in StoreKit — iOS 17

The StoreKit views APIs provide UI to help us build a store for our in-app purchases. Available in-app purchase views are,

Let’s explore them one by one…

👉 StoreView

It merchandises a collection of in-app purchase products.

A StoreView displays a collection of in-app purchase products, including their localized names, descriptions, and prices, and displays a purchase button.

  • StoreView needs product identifiers for the view to load the in-app purchases from AppStore or the PuchaseConfiguration provided during development.
   StoreView(ids: items)
StoreView

Looks quite boring…. worry not

Let’s customise the view by providing an icon/image for each product.

    let icons = ["dishtv", "hbo", "disney", "we"]
/// 2. Customised UI
StoreView(ids: items) { _ in
Image(icons.randomElement() ?? "we")
.resizable()
.frame(width: 60, height: 60)
.padding(.all, 8)
}.background(.background.secondary) // background for the view
}
Customized StoreView

By default, the StoreView arranges products in rows. If the view has enough horizontal space available, the store adds columns.

iPhone 14 Pro Max

👉 ProductView

A ProductView shows information about an in-app purchase product. Only one product view and not the list.

    ProductView(id: "1_week") {
Image("hbo")
}
Product View

We can add a standard border to an icon used by a ProductView.

    ProductView(id: "1_week") {
Image("hbo")
.productIconBorder()
}
productIconBorder

Still, it looks like a row in a list.

Worry not,

We can configure the in-app purchase product style for a view using the productViewStyle(_:) modifier.

    ProductView(id: "1_week") {
Image("hbo")
.productIconBorder()
}.productViewStyle(.regular)

Getting built-in product view styles

  • regular: A product view style that uses a standard, platform-appropriate layout.
.productViewStyle(.regular)
  • compact: Layouts where less space is available or for displaying more items in a small amount of space.
.productViewStyle(.compact)
  • large: Layouts where the in-app purchase content is prominent.
.productViewStyle(.large)
  • automatic: If don’t set anything then it's automatic by default. Based on the context, and space it displays one of the above styles.

You can customise the background of ProductVie.

    ProductView(id: "1_week") {
Image("hbo")
.productIconBorder()
}.padding()
.productViewStyle(.large)
.background(.background.secondary, in: .rect(cornerRadius: 20))
productViewStyle(.large).background(.background.secondary)
The designer is not happy?

Worry Not… 👉 Let’s Customise the ProductViewStyle

We can customise the view style for all the states like .loading, .unavailable, .failure, and .success state while trying to reload the in-app product.

struct CustomProductViewStyle: ProductViewStyle {
func makeBody(configuration: Configuration) -> some View {
switch configuration.state {
case .success(let product):
VStack(alignment: .center) {
configuration.icon
.padding()
.background(.cyan)
.clipShape(Circle())
Text(product.displayName)
.font(.largeTitle)
.foregroundColor(.blue)
Button(product.displayPrice) {}.tint(.mint)
}
case .loading:
VStack(alignment: .center) {
Text("Loading...")
}
case .unavailable:
VStack(alignment: .center) {
Text("Product not available...")
}
case .failure(let error):
VStack(alignment: .center) {
Text(error.localizedDescription)
}
@unknown default:
Text("Unknown error")
}
}
}
Conformance to ProductViewStyle

Design Product listing with ProductViewStyle to promote specific products.

Custom product listing with iOS 17 ProductView combination with different product styles.

NOTE: We can customize the default views to match our app by using our icons, backgrounds, and other styling to match your app.

Dark Mode

👉 SubscriptionStoreView

It automatically collects all the product ids from auto-renewable subscriptions and shows them on the screen.

- Only one subscription

SubscriptionStoreView(productIDs: StoreKitManager().productIds)
Only one AutoRenewal Subscription

- Multiple subscriptions

SubscriptionStoreView(productIDs: StoreKitManager().productIds)
.background(alignment: .leading, content: {
Image("ott-platforms")
.resizable()
})

Customise the SubsciptionStoreView

.subscriptionStorePolicyDestination automatically displays buttons for the terms of service and privacy policy that you submit in App Store Connect.

.subscriptionStorePolicyForegroundStyle sets the style for the terms of service and privacy policy buttons in case not able to see/match them in your design.

.subscriptionStoreButtonLabel gives any title to the specified button.

.subscriptionStoreControlIcon provide a custom icon for the specific purchase product.

.subscriptionStorePickerItemBackground set a background to the purchase item container.

SubscriptionStoreView(productIDs: StoreKitManager().productIds)
.subscriptionStorePolicyDestination(url: URL(string: "https://www.google.com")!, for: .privacyPolicy)
.subscriptionStoreControlBackground(.automatic)
.subscriptionStoreButtonLabel(.displayName)
.subscriptionStoreControlIcon { _,_ in
Image("hbo")
.resizable()
.frame(width:30, height:30)
}
.subscriptionStoreSignInAction({
print("go here....")
})

Add Ons:

  • Adopts the dark and light modes by default.
  • StoreKit manages the layouts across all platforms, so the views look great on any device.
  • Provide lots of customisation options for provided view styles.

Here is the COMPLETE CODE for reference.

--

--

Santosh Botre

Take your time to learn before develop, examine to make it better, and eventually blog your learnings.