In-app purchases in SwiftUI

Photo by Pixabay on Pexels.com

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() {
        super.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
        request.start()
    }
    
    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 {
            self.objectWillChange.send()
            }
        }
    }
}


More to come…

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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: