专为 SwiftUI 设计的轻量级 StoreKit2 包装器,让应用内购买的实现更加简单。
请参阅 DevTutor 中详细的 StoreKitHelper 文档,其中包括多个快速入门示例、自定义支付界面示例和 API 参考,提供全面的示例和指导。
- 🚀 SwiftUI 原生: 专为 SwiftUI 设计,支持
@ObservableObject和@EnvironmentObject - 💡 简洁 API: 干净直观的应用内购买管理接口
- 🔄 自动更新: 实时交易监控和状态更新
- ✅ 类型安全: 基于协议的产品定义,提供编译时安全性
- 🧪 可测试: 完全可测试的架构,测试用例覆盖 ExampleTests.swift/StoreKitHelperTests.swift
在 SwiftUI 应用程序的入口点创建并注入一个 StoreContext 实例,它负责加载产品列表和跟踪购买状态。
import StoreKitHelper
enum AppProduct: String, InAppProduct {
case lifetime = "focuscursor.lifetime"
case monthly = "focuscursor.monthly"
var id: String { rawValue }
}
@main struct DevTutorApp: App {
@StateObject var store = StoreContext(products: AppProduct.allCases)
var body: some Scene {
WindowGroup {
ContentView().environmentObject(store)
}
}
}StoreContext 现在提供三态购买状态。应用启动时,purchaseStatus 会先处于 .loading,直到 Transaction.currentEntitlements 首次同步完成。在这段时间里,hasPurchased 和 hasNotPurchased 都会返回 false,从而避免启动阶段被误判成“未购买”。
switch store.purchaseStatus {
case .loading:
// 正在同步购买状态
case .purchased:
// ✅ 用户存在有效购买
case .notPurchased:
// 🧾 用户当前没有有效购买
}推荐写法:
@EnvironmentObject var store: StoreContext
var body: some View {
switch store.purchaseStatus {
case .loading:
ProgressView("正在检查购买状态...")
case .purchased:
// ✅ 用户已购买 - 显示完整功能
case .notPurchased:
// 🧾 用户未购买 - 显示受限内容或提示购买
}
}默认购买调用方式保持不变:
await store.purchase(product)如果需要传递 StoreKit 的购买选项,现在也可以直接透传:
await store.purchase(product, options: [
.appAccountToken(appAccountToken)
])兼容旧写法:
@EnvironmentObject var store: StoreContext
var body: some View {
if store.hasResolvedPurchaseStatus == false {
ProgressView("正在检查购买状态...")
} else if store.hasNotPurchased == true {
// 🧾 用户未购买 - 显示受限内容或提示购买
} else if store.hasPurchased == true {
// ✅ 用户已购买 - 显示完整功能
}
}使用 StoreKitHelperView 直接显示应用内购买弹窗视图,并通过链式 API 配置各种参数。
struct PurchaseContent: View {
@EnvironmentObject var store: StoreContext
var body: some View {
let locale: Locale = Locale(identifier: Locale.preferredLanguages.first ?? "en")
StoreKitHelperView()
.environment(\.locale, .init(identifier: locale.identifier))
.environment(\.pricingContent, { AnyView(PricingContent()) })
.environment(\.popupDismissHandle, {
// 弹窗被关闭时触发(例如用户点击关闭按钮)
store.isShowingPurchasePopup = false
})
.environment(\.termsOfServiceHandle, {
// 点击【服务条款】按钮时触发的操作
})
.environment(\.privacyPolicyHandle, {
// 点击【隐私政策】按钮时触发的操作
})
.frame(maxWidth: 300)
.frame(minWidth: 260)
}
}点击打开付费产品列表界面。
struct ContentView: View {
@EnvironmentObject var store: StoreContext
var body: some View {
if store.hasNotPurchased == true, store.isLoading == false {
PurchasePopupButton()
.sheet(isPresented: $store.isShowingPurchasePopup) {
PurchaseContent()
}
}
}
}跟 StoreKitHelperView 差不多,选择购买项进行支付。
struct PurchaseContent: View {
@EnvironmentObject var store: StoreContext
var body: some View {
let locale: Locale = Locale(identifier: Locale.preferredLanguages.first ?? "en")
StoreKitHelperSelectionView()
.environment(\.locale, .init(identifier: locale.identifier))
.environment(\.pricingContent, { AnyView(PricingContent()) })
.environment(\.popupDismissHandle, {
// 弹窗被关闭时触发(例如用户点击关闭按钮)
store.isShowingPurchasePopup = false
})
.environment(\.termsOfServiceHandle, {
// 点击【服务条款】按钮时触发的操作
})
.environment(\.privacyPolicyHandle, {
// 点击【隐私政策】按钮时触发的操作
})
.frame(maxWidth: 300)
.frame(minWidth: 260)
}
}protocol InAppProduct: CaseIterable {
var id: String { get }
}enum PurchaseStatus {
case loading
case purchased
case notPurchased
}products: [Product]- 从 App Store 获取的可用产品列表purchasedProductIDs: Set<String>- 已购买产品标识符的集合purchaseStatus: PurchaseStatus- 当前购买状态:.loading、.purchased、.notPurchasedhasResolvedPurchaseStatus: Bool- 首次购买状态同步是否已完成hasNotPurchased: Bool- 在购买状态完成解析后,用户是否未购买任何产品hasPurchased: Bool- 在购买状态完成解析后,用户是否已购买任何产品isLoading: Bool- 产品是否正在加载中errorMessage: String?- 当前错误信息(如有)
purchase(_ product: Product, options: Set<Product.PurchaseOption> = [])- 购买指定产品,并可选透传 StoreKit 购买参数restorePurchases()- 恢复之前的购买isPurchased(_ productID: ProductID) -> Bool- 根据 ID 检查产品是否已购买isPurchased(_ product: InAppProduct) -> Bool- 检查产品是否已购买product(for productID: ProductID) -> Product?- 根据 ID 获取产品product(for product: InAppProduct) -> Product?- 根据 InAppProduct 获取产品
基于 MIT 许可证授权。
