Community-maintained Agent Skills for complete Swift and Apple-platform app delivery.
73
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Medium
Suggest reviewing before use
Use this reference for app-lifetime transaction observation, current entitlements, subscription status, revocation, Family Sharing, restore, and reconciliation. Product merchandising and the initiating purchase call are covered in products-and-purchases.md.
Start one Transaction.updates listener during app initialization and retain it for the app lifetime. It receives transactions created or changed outside the initiating purchase call, including Ask to Buy approval, purchases on another device, renewals, refunds, revocations, Family Sharing changes, and unfinished transactions StoreKit emits after launch.
final class StoreManager: Sendable {
let updatesTask: Task<Void, Never>
init(fulfillment: FulfillmentService) {
updatesTask = Task(priority: .background) {
for await result in Transaction.updates {
guard case .verified(let transaction) = result else { continue }
do {
try await fulfillment.reconcile(transaction)
await transaction.finish()
} catch {
// Leave unfinished for durable retry and surface diagnostics.
}
}
}
}
}Choose actor or @MainActor isolation from the state the manager owns; don't copy this shape blindly. Keep UI mutations on the appropriate actor and make fulfillment idempotent.
Transaction.currentEntitlements emits the latest transaction that currently entitles the customer to:
It excludes consumables and refunded/revoked products. Apply the app's expiration policy to non-renewing subscriptions. Rebuild entitlement state from a fresh local set so removed/revoked products disappear.
func loadEntitledProductIDs() async -> Set<String> {
var result = Set<String>()
for await verification in Transaction.currentEntitlements {
guard case .verified(let transaction) = verification,
transaction.revocationDate == nil else { continue }
if transaction.productType == .nonRenewing,
transaction.expirationDate.map({ $0 <= .now }) ?? true {
continue
}
result.insert(transaction.productID)
}
return result
}Reconcile on launch and when transaction updates arrive. Refreshing on foreground can be appropriate for entitlement-sensitive screens, but don't start duplicate lifetime listeners from views.
Use transaction information as the access authority. UI configuration values such as hasCurrentEntitlement can customize merchandising but aren't a substitute for verified entitlement checks.
Where available for the deployment target, product-scoped current-entitlement sequences or SwiftUI entitlement task modifiers can drive a focused screen. Preserve the same verification, revocation, and product-type rules as collection-wide reconciliation.
Consumables require a separate delivered-balance/history source. Non-renewing subscriptions require app/server expiration persistence because StoreKit doesn't define their access window for the product.
Use Product.SubscriptionInfo.status(for:) or the subscription information associated with loaded products when the UI needs renewal details beyond a yes/no entitlement.
Verify both transaction and renewal information. Interpret states deliberately:
| State | Typical access policy |
|---|---|
.subscribed | Grant access |
.inGracePeriod | Grant access while billing recovery continues |
.inBillingRetryPeriod | Follow product policy; don't report as a successful renewal |
.expired | Remove subscription access unless another entitlement applies |
.revoked | Remove access and reconcile immediately |
Use renewal information for auto-renew status, expiration reason, billing retry, price-increase consent, and eligible offer IDs. Do not infer these details from a single product purchase result.
Family Sharing ownership and revocation arrive through verified transactions. Avoid permanently binding shared access to a local Boolean.
StoreKit automatically makes current transactions available after reinstall or on another device. Always derive access proactively from Transaction.currentEntitlements.
Provide a visible Restore Purchases mechanism when expected by the store/paywall. AppStore.sync() forces synchronization and may prompt for App Store authentication, so call it only in response to an explicit user action—not automatically at launch.
func restore() async throws {
try await AppStore.sync()
entitledProductIDs = await loadEntitledProductIDs()
}For non-renewing subscriptions and consumables, restoration depends on the app or server's own durable records.
Transaction.unfinished or launch updates when durable fulfillment needs explicit recovery.Advanced offers, billing recovery UI, refund requests, server validation, testing, and unfinished-transaction patterns are detailed in storekit-advanced.md.
.tessl-plugin
skills
accessorysetupkit
references
activitykit
adattributionkit
references
alarmkit
references
app-clips
app-intents
app-store-optimization
app-store-review
apple-on-device-ai
appmigrationkit
audioaccessorykit
references
authentication
references
avkit
background-processing
references
browserenginekit
callkit
references
carplay
cloudkit
contacts-framework
references
core-bluetooth
references
core-data
core-motion
references
core-nfc
references
coreml
references
cryptokit
cryptotokenkit
references
debugging-instruments
device-integrity
references
dockkit
energykit
references
eventkit
financekit
references
focus-engine
gamekit
healthkit
references
homekit
references
ios-accessibility
ios-app-workflow
references
ios-ettrace-performance
ios-localization
ios-memgraph-analysis
ios-networking
ios-simulator
references
metrickit
references
musickit
references
natural-language
references
paperkit
references
passkit
references
pdfkit
pencilkit
references
permissionkit
references
photokit
push-notifications
realitykit
references
relevancekit
references
scenekit
sensorkit
speech-recognition
references
spritekit
storekit
swift-api-design-guidelines
swift-architecture
references
swift-charts
swift-codable
references
swift-code-review
swift-concurrency
swift-formatstyle
references
swift-language
swift-security
references
swift-testing
swiftdata
swiftlint
swiftui-animation
swiftui-gestures
references
swiftui-layout-components
swiftui-liquid-glass
references
swiftui-patterns
swiftui-performance
swiftui-responsive-layout
swiftui-uikit-interop
swiftui-webkit
tabletopkit
tipkit
vision-framework
weatherkit
references