In-app purchases in SwiftUI

Photo by Pixabay on

I am currently working on implementing in-app purchases into my first app. I’ve set up the product identifiers, pricing and descriptions in App Store Connect and have the code to request a return of the products.

The main issue I have been tackling during this process is how to filter the products that are returned from the app store without hard-coding specific identifiers into the views.

Also it’s interesting how little information there is out there on how to integrate in-app purchases with SwiftUI. Even the developer demo from Apple is based on using UIKit. So I will also post how I solved this.

Before we get to that, here’s a snippet of code that handles the request and store of products returned from the app-store.

import StoreKit
import Combine

class IAPManager: NSObject {
    static let shared = IAPManager()
    private override init() {

    //here we get the product id's stored in a .plist file and request them from the App Store

    func getProducts(resource: String) {
        let productIDs = Set(getProductIDs(resource: resource))
        let request = SKProductsRequest(productIdentifiers: productIDs)
        request.delegate = self
    func getProductIDs(resource: String) -> [String] {
        guard let url = Bundle.main.url(forResource: resource, withExtension: "plist") else { return [] }
        do {
            let data = try Data(contentsOf: url)
            let productIDs = try PropertyListSerialization.propertyList(from: data, options: .mutableContainersAndLeaves, format: nil) as? [String] ?? []
            return productIDs
        catch {
            return []

extension IAPManager: SKProductsRequestDelegate, SKRequestDelegate {
    // returns app store products to ProductStore which is an Observable Object and one we will access in the SwiftUI views

    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        let products = response.products
        if products.count > 0 {
            ProductsStore.shared.items = products
        } else {  

final class ProductsStore: ObservableObject, Identifiable {
    static let shared = ProductsStore()
    var items:[SKProduct] = []
        willSet {
          DispatchQueue.main.async {

More to come…

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: