How to Back Up and Restore Consumable In-App Purchases with iCloud or Dropbox

Introduction to Consumable In-App Purchases and Backup/Restore Process

As a developer, it’s essential to understand how to handle in-app purchases (IAP) in your app. One type of IAP is consumable, which allows users to purchase items that can be used up over time. In this article, we’ll explore the process of backing up and restoring consumable in-app purchases tracked in NSUserDefaults to/from iCloud or Dropbox.

What are Consumable In-App Purchases?

Consumable IAPs allow users to purchase items that can be used up over time. For example, a game might sell power-ups or bonuses that can be used once. These types of purchases are typically represented as consumables in the app’s database.

How do Consumable In-App Purchases Work?

When a user makes a consumable IAP purchase, the app receives a response from the App Store containing information about the purchased item. The app then updates its internal state to reflect the new purchase.

In our case, we’re tracking the number of times each product identifier has been bought in NSUserDefaults. This means that every time a user makes a consumable IAP purchase, we increment the count for that product identifier.

Why is it Challenging to Backup and Restore Consumable In-App Purchases?

The StoreKit framework doesn’t provide a restoreCompletedTransactions method specifically for consumable IAPs. This means that when a user reinstall the app, changes the device, or restores their device, there’s no built-in way to automatically restore their consumable purchases.

Solution: Modifying Purchase Definitions

One solution discussed in the comments is to modify our purchase definitions to use a series of non-consumable purchases instead. For example:

  • P1: allow first 10 items or first 10 after a free set (or 10 items total)
  • P2: allow next 10 items (or twenty items total)
  • P3: allow a further 10 items (or 30 items total)
  • Pn: allow the last set of ten items you think is reasonable.

By using this approach, we can take advantage of Apple’s built-in restoreCompletedTransactions method for non-consumable purchases. We can then modify our app to use these new purchase definitions and implement a restore process that automatically updates our internal state with the purchased quantities.

Modifying Application Code

To implement this solution, we’ll need to make changes to our application code. Here’s an example of how we might modify our ViewController class to use the new purchase definitions:

// ViewController.m

#import <UIKit/UIKit.h>
#import "PurchaseManager.h"

@interface ViewController : UIViewController

@property (nonatomic, strong) PurchaseManager *purchaseManager;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.purchaseManager = [[PurchaseManager alloc] init];
}

- (IBAction)purchaseItem:(id)sender {
    // Get the current purchase quantity for the item
    NSArray *products = [[NSApp storeKitEnabledProductsForBundleIdentifier:@"YOUR_BUNDLE_ID"] copy];
    NSString *productIdentifier = [products firstObject];
    
    // Check if the product is available
    if ([self.purchaseManager isProductAvailable:productIdentifier]) {
        // Make the purchase
        [self.purchaseManager makePurchase:productIdentifier quantity:self.purchaseManager.currentQuantity + 1];
        
        // Update our internal state with the new quantity
        self.purchaseManager.updateQuantityForProduct:productIdentifier quantity:self.purchaseManager.currentQuantity + 1;
    } else {
        // Handle the case where the product is not available
    }
}

@end

Introducing iCloud and Dropbox as Backup Options

Now that we’ve discussed how to modify our application code to use non-consumable purchases, let’s talk about backing up and restoring our consumable IAPs using iCloud or Dropbox.

iCloud provides a convenient way to store data on Apple devices. We can use the iCloudStorage framework to sync our NSUserDefaults with iCloud. This means that whenever we make changes to our internal state, they’ll be automatically synced with iCloud.

Dropbox is another popular cloud storage service that offers syncing capabilities for iOS apps. We can use the Dropbox SDK to store and retrieve data from our app’s NSUserDefaults.

Implementing iCloud Backup

To implement iCloud backup, we’ll need to add some additional code to our application. Here’s an example of how we might modify our ViewController class to include iCloud syncing:

// ViewController.m

#import <UIKit/UIKit.h>
#import "PurchaseManager.h"
#import "iCloudStorage.h"

@interface ViewController : UIViewController

@property (nonatomic, strong) PurchaseManager *purchaseManager;
@property (nonatomic, strong) iCloudStorage *cloudStorage;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.purchaseManager = [[PurchaseManager alloc] init];
    self.cloudStorage = [[iCloudStorage alloc] initWithStoreKitEnabledProductsForBundleIdentifier:@"YOUR_BUNDLE_ID"];
}

- (IBAction)purchaseItem:(id)sender {
    // Get the current purchase quantity for the item
    NSArray *products = [[NSApp storeKitEnabledProductsForBundleIdentifier:@"YOUR_BUNDLE_ID"] copy];
    NSString *productIdentifier = [products firstObject];
    
    // Check if the product is available
    if ([self.purchaseManager isProductAvailable:productIdentifier]) {
        // Make the purchase
        [self.purchaseManager makePurchase:productIdentifier quantity:self.purchaseManager.currentQuantity + 1];
        
        // Update our internal state with the new quantity
        self.purchaseManager.updateQuantityForProduct:productIdentifier quantity:self.purchaseManager.currentQuantity + 1;
    }
    
    // Sync our NSUserDefaults with iCloud
    [self.cloudStorage syncWithStoreKitEnabledProductsForBundleIdentifier:@"YOUR_BUNDLE_ID"];
}

@end

Implementing Dropbox Backup

To implement Dropbox backup, we’ll need to add some additional code to our application. Here’s an example of how we might modify our ViewController class to include Dropbox syncing:

// ViewController.m

#import <UIKit/UIKit.h>
#import "PurchaseManager.h"
#import "DropboxSDK.h"

@interface ViewController : UIViewController

@property (nonatomic, strong) PurchaseManager *purchaseManager;
@property (nonatomic, strong) DropboxSDK *dropboxSDK;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.purchaseManager = [[PurchaseManager alloc] init];
    self.dropboxSDK = [[DropboxSDK alloc] initWithAppKey:@"YOUR_APP_KEY"];
}

- (IBAction)purchaseItem:(id)sender {
    // Get the current purchase quantity for the item
    NSArray *products = [[NSApp storeKitEnabledProductsForBundleIdentifier:@"YOUR_BUNDLE_ID"] copy];
    NSString *productIdentifier = [products firstObject];
    
    // Check if the product is available
    if ([self.purchaseManager isProductAvailable:productIdentifier]) {
        // Make the purchase
        [self.purchaseManager makePurchase:productIdentifier quantity:self.purchaseManager.currentQuantity + 1];
        
        // Update our internal state with the new quantity
        self.purchaseManager.updateQuantityForProduct:productIdentifier quantity:self.purchaseManager.currentQuantity + 1;
    }
    
    // Sync our NSUserDefaults with Dropbox
    [self.dropboxSDK syncWithFolderPath:@"YOUR_FOLDER_PATH"];
}

@end

Conclusion

In this article, we’ve explored the process of backing up and restoring consumable in-app purchases tracked in NSUserDefaults to/from iCloud or Dropbox. We discussed how to modify our application code to use non-consumable purchases and implemented a restore process that automatically updates our internal state with the purchased quantities.

We also introduced iCloud and Dropbox as backup options and provided examples of how to implement syncing capabilities for each service.

By following these steps, you can ensure that your app’s consumable IAPs are backed up and restored securely, providing a better user experience for your customers.


Last modified on 2023-06-20