Add the SDK to a SwiftUI App

If you have an application built using SwiftUI from scratch, there are a few different considerations from the standard iOS SDK setup.

Add the SDK to your project

To start with, we'll add the Nami SDK to your application via the Swift Package Manager like so -

1378

To add the Nami SDK, we'll give it the GitHub location of the Nami Apple repository - enter the URL:

https://github.com/namiml/NamiSDK-SwiftPackageManager

1198

The Swift Package Manager will then go through a few steps, and add the Nami SDK to your project.

Once added, there is one more project related step you need to take in order to ensure SwiftUI previews will continue to load correctly - we need to tell Xcode to ignore arm64 binaries when running in the simulator (if you are running on Apple Silicon you may not need this step).

To fix this, go into your project Build Settings in Xcode, search for "excluded", and set up an exclusion like so - Make sure you enter "arm64" all lowercase, and only for "Any iOS Simulator SDK" instead of for Debug generally:

2042

Add Nami SDK configuration to your app startup.

In non-SwiftUI development, there is an AppDelegate where you add Nami configuration code to make sure Nami is started on app startup.

For SwiftUI, we need to add the configuration to your App class, as in this example project (note the added "import Nami" in addition to the Nami configuration code on init):

import SwiftUI
import Nami

@main
struct NamiSwiftUIDemoApp: App {
  init() {
    let namiConfig = NamiConfiguration(appPlatformID: "YOU_APP_ID_HERE")
    namiConfig.logLevel = .warn
    Nami.configure(namiConfig: namiConfig )
  }  
  var body: some Scene {....}    
}

After adding that code, if you build and run you will see any paywalls you have configured show up in the application if you have auto-raise rules configured. Paywalls will not show up in screen previews.

Adapting Nami callbacks to SwiftUI Publishers

We can make use of any of the callbacks Nami lets you configure, to act as a publisher so that you can react to changes in SwiftUI views. In the future there may be additions to the Nami SDK to act as publishers, for the moment you can create a publisher adaptor for any aspect of the callbacks you find useful for your application.

One of the most useful signals form the Nami SDK to adapt is the NamiEntitlementManager entitlement change handler. This is called when Entitlements for an application change - an entitlement change will occur when any products related to an entitlement are purchased, such as a monthly or yearly subscription and mean you don't have to look for specific productIDs in your application.

We'll create a publishing adaptor by adding the following code to our application, it can go in any file at the top level:

import Nami

/// This datasource is a publisher adaptor for subscription changes from the Nami SDK
class NamiDataSource: ObservableObject {
  /// This variable is modified my Nami depending on subscription status
  @Published var subscribed = false
  
  init() {
    // On first init, check to see if subscription is active.
    subscribed = (NamiEntitlementManager.activeEntitlements().count > 0)
    
    // If you'd rather work with purchase, here's an alternative, though we always recommend working with entitlements when possible
    purchased = NamiPurchaseManager.allPurchases().count > 0
        
    // Now register a change handler that will set the variable when entitlements change
    NamiEntitlementManager.registerEntitlementsChangedHandler { (activeEntitlements) in
      // If any entitlements exist we'll consider the subscription active, you could also look for specific entitlements here.
      self.subscribed = (activeEntitlements.count > 0)
    }
  }
}

This particular DataSource adds a NamiEntitlementManager change handler, but you could similarly register any other Nami change handler, and add other variables into this same class to publish other kinds of changes.

Once you have a NamiDataSource defined, we can add it to a SwiftUI View:

struct ContentView: View {
  @ObservedObject var namiDataSource: NamiDataSource
  ...
}

Something needs to create the NamiDataSource object for that View, since we added that variable to the ContentView in the example above whatever creates it needs to pass in a NamiDataSource like so:

ContentView(namiDataSource: NamiDataSource())

Using published Nami variables and calling the Nami SDK in SwiftUI

Now that we have registered a handler to publish entitlement changes, we can take the last step of adapting our view code to react to changes in entitlements, and also call into Nami frothier operations like raising paywalls.

To select between two possible views based on the subscription status is now as simple as:

if namiDataSource.subscribed {
  Text("Active")
  .foregroundColor(.green)
  .font(.title)
} else {
  Text("Inactive")
  .foregroundColor(.red)
  .font(.title)
}

At any time from a SwiftUI control, we can also call into the Nami SDK to make changes, or to request operations like a paywall be raised:

Button(action:{
  // When subscribe button is pressed, we ask Nami to raise the paywall
  NamiPaywallManager.raisePaywall(fromVC: nil)
}) {
  Text("Subscribe")
  .background(Color.white)
  .foregroundColor(.blue)
  .font(.callout)
}

Note that for RaisePaywall to show products in an IOS 14 simulator, you'll need to set up a StoreKitConfiguration with products that match the products you've defined in Nami for your paywall. Please see our guide on Adapting to Xcode 12 and iOS 14 changes for StoreKit testing for more details.

You are now ready to add Nami to your SwiftUI application wherever needed!