Post

Using RevenueCat for Widgets

For my first application, I am trying to find the right balance between free and paid features. Once of the things I have been considering is whether or not to make my widgets (or some portion of them) a premium feature. As I was looking into how to implement that with RevenueCat I had a little trouble getting it all figured out, so I decided I would share my experience.

The first thing that I needed to do was update my RevenueCat initialization to store the data in my App Storage so that I could share it with my widget. This was relatively straight forward.

1
2
3
4
5
6
7
8
init() {
        Purchases.configure(
          with: Configuration.Builder(withAPIKey: "appl_XXXXX")
            .with(userDefaults: .init(suiteName: "group.com.example.application")!)
            .build()
        )
        Purchases.logLevel = .debug
    }

In my TimelineProvider, I imported the RevenueCat Framework and added an initialization function that also used the local app storage.

1
2
3
4
5
6
7
func configureRevenueCat() {
    Purchases.configure(
        with: Configuration.Builder(withAPIKey: "appl_XXXXX")
        .with(userDefaults: .init(suiteName: "group.com.example.application")!)
        .build()
    )
}

Next, I added the Purchases function around my timeline calls. I added a parameter called isPro as a simple boolean in my Entry struct to identify if the user has a subscription.

1
2
3
4
5
6
7
8
9
10
11
func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
    configureRevenueCat()
    Purchases.shared.getCustomerInfo { customerInfo, _ in
        let isPro = customerInfo?.entitlements["full"]?.isActive == true
        ...
        let entry = SimpleEntry(date: Date.now, isPro: isPro, data: data)

        let timeline = Timeline(entries: [entry], policy: .atEnd)
        completion(timeline)
    }
}

Finally, I needed to add the RevenueCat framework to my widget target so that it will get built with it. I’m sure that most people know that, but it wasn’t in any of the documentation, so it had me stumped for a minute. To do that you go to the Project page, select the widget target, and under the General tab add the RevenueCat package to Frameworks and Libraries.

With RevenueCat now building, I could then add code to my view to check if the user has a subscription.

1
2
3
4
5
6
7
8
if !entry.isPro {
    VStack {
        Image(systemName: "lock.circle")
        Text("Subscribe to unlock this widget")
    }
} else {
    ...
}

I have not decided if I am going to use it or not, but it is good to know that it is an option.