StoreKitHelper/README.zh.md
2025-12-29 17:58:04 +08:00

12 KiB

使用 我的应用 也是一种 支持 我的方式:
Deskmark Keyzer Vidwall Hub VidCrop Vidwall Mousio Hint Mousio Musicer Audioer FileSentinel FocusCursor Videoer KeyClicker DayBar Iconed Mousio Quick RSS Quick RSS Web Serve Copybook Generator DevTutor for SwiftUI RegexMate Time Passage Iconize Folder Textsound Saver Create Custom Symbols DevHub Resume Revise Palette Genius Symbol Scribe

StoreKit Helper

English

专为 SwiftUI 设计的轻量级 StoreKit2 包装器,让应用内购买的实现更加简单。

StoreKit Helper

文档

请参阅 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 中的 hasNotPurchasedhasPurchased 属性来检查用户是否已购买,然后动态显示不同的界面内容。例如:

@EnvironmentObject var store: StoreContext

var body: some View {
    if store.hasNotPurchased == true {
        // 🧾 用户未购买 - 显示受限内容或提示购买
    } else {
        // ✅ 用户已购买 - 显示完整功能
    }
    if store.hasPurchased == true {
        // ✅ 用户已购买 - 显示完整功能
    } else {
        // 🧾 用户未购买 - 显示受限内容或提示购买
    }
}

StoreKitHelperView

使用 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 {
            PurchasePopupButton()
                .sheet(isPresented: $store.isShowingPurchasePopup) {
                    PurchaseContent()
                }
        }
    }
}

StoreKitHelperSelectionView

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)
    }
}

API 参考

InAppProduct 协议

protocol InAppProduct: CaseIterable {
    var id: String { get }
}

StoreContext 属性

  • products: [Product] - 从 App Store 获取的可用产品列表
  • purchasedProductIDs: Set<String> - 已购买产品标识符的集合
  • hasNotPurchased: Bool - 用户是否未购买任何产品
  • hasPurchased: Bool - 用户是否已购买任何产品
  • isLoading: Bool - 产品是否正在加载中
  • errorMessage: String? - 当前错误信息(如有)

StoreContext 方法

  • purchase(_ product: Product) - 购买指定产品
  • restorePurchases() - 恢复之前的购买
  • isPurchased(_ productID: ProductID) -> Bool - 根据 ID 检查产品是否已购买
  • isPurchased(_ product: InAppProduct) -> Bool - 检查产品是否已购买
  • product(for productID: ProductID) -> Product? - 根据 ID 获取产品
  • product(for product: InAppProduct) -> Product? - 根据 InAppProduct 获取产品

许可证

基于 MIT 许可证授权。