Dev Diary Day 5: StoreKit 2 Subscription Implementation for a Memo-to-Email App

· Source: LLM on Medium · Field: Technology & Digital — Software Development & Engineering, E-commerce & Digital Commerce · Depth: Intermediate, long

Summary

This dev diary details the complete StoreKit 2 subscription implementation for "Simple Memo," a memo-to-email iOS app, focusing on both code and critical non-code requirements for App Store review. The app uses a three-tier monetization model: a 7-day free trial, a free plan with 3 sends/day, and an unlimited Premium plan. Key technical aspects include using StoreKit 2 with Swift Concurrency for on-device transaction verification, a `SubscriptionManager` singleton with `@MainActor` and `ObservableObject`, and a `Task.detached` transaction listener for `Transaction.updates`. The implementation also covers robust product loading with retry mechanisms, handling `product.purchase()` outcomes (success, userCancelled, pending), and mandatory "Restore Purchases" functionality via `AppStore.sync()`. The author emphasizes that 80% of in-app purchase challenges lie outside the code, primarily in App Store Connect configuration, Guideline 3.1.2 compliance, and navigating Sandbox testing quirks.

Key takeaway

For iOS developers implementing in-app subscriptions, you must meticulously address Apple's Guideline 3.1.2 requirements, including clear pricing, auto-renewal disclosure, legal links, and a "Restore Purchases" button. Your paywall UI and underlying StoreKit 2 implementation should anticipate and gracefully handle network issues and Sandbox environment inconsistencies to prevent user frustration and App Store rejections. Focus on a robust, user-centric payment flow from the outset.

Key insights

StoreKit 2 simplifies iOS in-app purchases, but App Store review compliance and robust error handling remain critical.

Principles

Method

Implement StoreKit 2 using Swift Concurrency, a `@MainActor` singleton for state, and a `Task.detached` listener for `Transaction.updates`, ensuring `transaction.finish()` is called post-processing.

In practice

Topics

Best for: Software Engineer, Product Manager

Related on AIssential

Open in AIssential →

Editorial summary, takeaway, and curation by AIssential. Original article published by LLM on Medium.