In-app purchases in SwiftUI

Photo by Pixabay on Pexels.com

How do you implement in-app purchases with SwiftUI?

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. Hopefully you find this useful from my experience.

Here’s a snippet of code that handles the return of products to an in-app purchases view in SwiftUI. It is triggered by the purchased variable returning false prompting the user with a purchases view in order to progress.

This code is assuming you have already implemented IAP Manager in the same way you would for UIKit.

In-app purchases view

struct IAPView: View {
    var iap = IAPManager.shared
    @Binding var purchased: Bool
    @ObservedObject var productsStore: ProductsStore =
 ProductsStore.shared
    
    var body: some View {
        VStack (alignment: .leading) {
            Text(SectionType.availableProducts.description)
                .font(.title)
                .foregroundColor(.black)
                .padding(.leading)
            Spacer()
            List{
              ForEach (productsStore.getAvailableProductData(),
                         id: \.self) { product in
                    Button(action: {
                        self.iap.buy(product: product)
                    })
                    {
                     HStack {
                        VStack (alignment: .leading) {
                           Group{
                              Text(product.localizedTitle)
                               .font(.headline)
                              Text(product.localizedDescription)
                                .font(.subheadline)
                           }.foregroundColor(.black)
                        }
                        Spacer()
// Show the product's price in the local 
//currency returned by the App Store.
                            
                        Text(String(self.iap.formatPrice(for: 
                          product) ?? Messages.priceUnavailable))
                        ButtonView(text: AppText.buyButtonTitle,
                         gameColor: AppNumbers.navyBlue)                                
                         .font(.subheadline)
                         .accessibility(label: 
                        Text(AppText.buyButtonTitle))
                    }
                 }
                }
            }
       }
    }
}

The Product Store


 import SwiftUI
 import StoreKit
 
 final class ProductsStore: ObservableObject, Identifiable {
     
     static let shared = ProductsStore()
     @Published var data = [SectionElement]()
     @Published var purchases = [String]()
          
    {
         willSet {
           DispatchQueue.main.async {
             self.objectWillChange.send()
             }
         }
     }
     
     /// If there are available products, return them.
     func getAvailableProductData() -> [SKProduct] {
         
         for section in self.data {
             if section.type == .availableProducts,
                let content = section.elements as? [SKProduct] {
                 return content
             }
         }
         return [SKProduct]()
     }
     
     ///returns true if the user has already purchased the resource
     func checkExistingPurchases(resourceFile: ProductIdentifiers) 
-> Bool {
         
         for identifier in resourceFile.identifiers! {
             for item in purchases {
                 if identifier == item {
                     return true
                 }
             }
         }
         return false
     }
 }


 /// A structure that is used to represent a list of products or
 purchases.
 struct SectionElement {
     /// Products/Purchases are organized by category.
     var type: SectionType
     /// List of products/purchases.
     var elements = [Any]()
 } 

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: