storekit
npx skills add https://github.com/johnrogers/claude-swift-engineering --skill storekit
Agent 安装分布
Skill 文档
StoreKit
StoreKit 2 patterns for implementing in-app purchases with async/await APIs, automatic verification, and SwiftUI integration.
Reference Loading Guide
ALWAYS load reference files if there is even a small chance the content may be required. It’s better to have the context than to miss a pattern or make a mistake.
| Reference | Load When |
|---|---|
| Getting Started | Setting up .storekit configuration file, testing-first workflow |
| Products | Loading products, product types, purchasing with Product.purchase() |
| Subscriptions | Auto-renewable subscriptions, subscription groups, offers, renewal tracking |
| Transactions | Transaction listener, verification, finishing transactions, restore purchases |
| StoreKit Views | ProductView, SubscriptionStoreView, SubscriptionOfferView in SwiftUI |
Core Workflow
- Create
.storekitconfiguration file first (before any code) - Test purchases locally in Xcode simulator
- Implement centralized
StoreManagerwith@MainActor - Set up
Transaction.updateslistener at app launch - Display products with
ProductViewor custom UI - Always call
transaction.finish()after granting entitlements
Essential Architecture
@MainActor
final class StoreManager: ObservableObject {
@Published private(set) var products: [Product] = []
@Published private(set) var purchasedProductIDs: Set<String> = []
private var transactionListener: Task<Void, Never>?
init() {
transactionListener = listenForTransactions()
Task { await loadProducts() }
}
}
Common Mistakes
-
Missing
.finish()calls on transactions â Forgetting to calltransaction.finish()after granting entitlements causes transactions to never complete. The user won’t see their purchase reflected. Always callfinish(). -
Unsafe StoreManager state â Shared
StoreManagerwithout@MainActorcan have race conditions. Multiple async tasks can update@Publishedproperties concurrently, corrupting state. Use@MainActorfor thread safety. -
No transaction listener at app launch â Not setting up
Transaction.updateslistener means app crashes or misses refunded/canceled purchases. Listen for transactions immediately in@main, not when user taps purchase button. -
Hardcoded product IDs â Hardcoded IDs make testing and localization hard. Use configuration files or environment variables for product IDs. Same applies to prices (fetch from App Store, don’t hardcode).
-
Ignoring verification failures â App Store verification fails silently sometimes. Not checking verification status means accepting unverified transactions (security risk). Always verify before granting entitlements.