StoreView
是 StoreKit 框架中的一个 SwiftUI 组件,专门用于展示应用内购买商品(包括一次性购买、消耗型商品和订阅)的集合视图。它比 ProductView
更强大,支持以列表、网格或其他布局形式展示多个商品,并提供统一的购买管理接口。
核心功能 #
- 多商品展示
支持通过商品 ID 数组或Product
对象数组,自动加载并展示多个商品。 - 自适应布局
默认根据商品类型(如订阅与非订阅)自动调整界面风格,也支持自定义布局。 - 订阅组管理
专门针对订阅商品,支持展示订阅组(Subscription Group)的选项(如月度/年度计划)。 - 与 StoreKit 深度集成
自动处理商品加载、购买流程、错误提示和交易验证,减少开发者代码量。
基本用法 #
1. 初始化方式 #
通过 商品 ID 数组 或 Product 对象数组 初始化:
import SwiftUI
import StoreKit
// 通过商品 ID 初始化(推荐)
struct StoreViewDemo: View {
var body: some View {
StoreView(ids: ["com.yourcompany.product1", "com.yourcompany.product2"])
}
}
// 通过 Product 对象初始化(需预先加载商品信息)
struct StoreViewDemo: View {
let products: [Product] // 通过 Product.products(for:) 加载
var body: some View {
StoreView(products: products)
}
}
2. 订阅组展示 #
若商品包含订阅组,StoreView
会自动分组展示选项:
StoreView(ids: ["subscription_monthly", "subscription_yearly"])
// 自动将同一订阅组的商品合并展示(如选择月度或年度计划)
高级配置 #
1. 设置展示样式 #
通过 storeViewStyle
修改布局样式(iOS 17+):
StoreView(ids: ["product1", "product2"])
.storeViewStyle(.grid) // 支持 .grid(网格)、.collection(集合)、.default(默认)
2. 自定义订阅组名称 #
为订阅组设置本地化名称:
StoreView(ids: ["subscription_monthly", "subscription_yearly"])
.subscriptionGroupLabel("Premium Access Plans") // 设置订阅组标题
3. 处理购买结果 #
通过 onInAppPurchaseCompletion
监听购买状态:
StoreView(ids: ["product1", "product2"])
.onInAppPurchaseCompletion { product, result in
switch result {
case .success(.success(let transaction)):
print("购买成功: \(transaction.productID)")
case .failure(let error):
print("购买失败: \(error.localizedDescription)")
default:
break
}
}
与 ProductView
的对比
#
特性 | ProductView | StoreView |
---|---|---|
展示对象 | 单个商品 | 多个商品或订阅组 |
布局复杂度 | 简单(单一商品) | 复杂(支持网格、列表等布局) |
订阅组支持 | 无 | 自动分组展示订阅选项 |
适用场景 | 展示独立商品(如游戏货币) | 展示完整商店页面(如订阅计划) |
代码示例:完整商店页面 #
struct FullStoreView: View {
@State private var errorMessage: String?
var body: some View {
NavigationStack {
StoreView(ids: ["subscription_monthly", "coins_100", "premium_theme"])
.storeViewStyle(.collection) // 集合视图样式
.subscriptionGroupLabel("订阅计划")
.navigationTitle("应用商店")
.toolbar {
Button("恢复购买") {
Task { try? await AppStore.sync() }
}
}
.alert("错误", isPresented: .constant(errorMessage != nil)) {
Button("确定", role: .cancel) { }
} message: {
Text(errorMessage ?? "")
}
}
}
}
使用注意事项 #
- 商品审核状态
确保所有商品在 App Store Connect 中已审核通过,否则StoreView
无法加载。 - 最低系统要求
- iOS 17.0+
- macOS 14.0+
- 沙盒测试
在 Xcode 中使用StoreKit Configuration
文件模拟购买流程,或在真机上使用沙盒账户测试。
常见问题 #
- 商品未显示?
检查商品 ID 是否正确,确保网络连接正常,且商品在 App Store Connect 中已批准。 - 如何自定义商品单元格?
StoreView
的 UI 深度集成系统样式,若需完全自定义,仍需使用ProductView
或手动实现。 - 支持跨平台吗?
是,StoreView
在 iOS、macOS、visionOS 等平台上自动适配样式。
官方文档扩展 #
通过 StoreView
,开发者可以快速构建符合苹果设计规范的多商品商店界面,尤其适合需要展示订阅选项的应用(如流媒体服务、付费会员等)。
对比 ProductView #
To achieve a custom layout, you can compose
ProductView
instances with other container views instead of using theStoreView
.
ProductView
和 StoreView
是 StoreKit 2 中两个不同的 SwiftUI 组件,分别针对不同的应用内购买(IAP)场景设计。以下是它们的核心区别和使用场景对比:
1. 功能定位 #
ProductView | StoreView | |
---|---|---|
目标对象 | 单个商品 | 多个商品或订阅组 |
核心能力 | 展示单个商品的基本信息和购买按钮 | 展示商品集合,支持复杂布局(如网格、列表)和订阅组管理 |
自动化程度 | 自动加载商品信息、格式化和购买逻辑 | 自动处理多商品加载、布局适配、订阅组分类 |
2. 使用场景 #
ProductView #
适用场景
- 需要展示单个商品(如游戏货币、一次性解锁功能)。
- 快速集成简单购买按钮,无需复杂界面设计。
- 在应用内分散的入口展示商品(如设置页中的“升级到高级版”按钮)。
示例代码
// 展示单个商品 struct UnlockProView: View { var body: some View { VStack { Text("升级到专业版") ProductView(id: "com.yourapp.pro_version") .productViewStyle(.compact) } } }
StoreView #
适用场景
- 需要展示多个商品或订阅计划(如订阅服务的月度/年度选项、商品包)。
- 构建完整的应用商店页面,支持复杂布局(如网格、列表)。
- 需要自动管理订阅组(Subscription Group)的展示和选择逻辑。
示例代码
// 展示多个商品和订阅组 struct SubscriptionStore: View { var body: some View { StoreView(ids: ["subscription_monthly", "subscription_yearly", "coins_100"]) .storeViewStyle(.grid) // 网格布局 .subscriptionGroupLabel("订阅计划") // 自定义订阅组标题 } }
3. 布局与定制化 #
ProductView | StoreView | |
---|---|---|
默认布局 | 垂直堆叠的商品信息+购买按钮 | 自动根据商品类型分组(如订阅与非订阅) |
布局控制 | 简单调整尺寸和按钮样式 | 支持 .grid (网格)、.collection (集合)、.default (列表) |
UI 定制性 | 较低(依赖系统样式) | 中等(可通过修饰符调整标题、布局,但单元格内容不可自定义) |
4. 订阅支持 #
ProductView | StoreView | |
---|---|---|
订阅组展示 | 不支持(需手动实现) | 自动将同一订阅组的商品合并展示,并提供选择界面(如月度 vs 年度) |
续订提示 | 无 | 自动显示订阅续订周期和优惠信息 |
5. 代码复杂度 #
ProductView
适用于极简场景,几行代码即可展示商品:ProductView(id: "product_id") .onInAppPurchaseCompletion { product, result in /* ... */ }
StoreView
适合多商品场景,但需注意商品加载和布局配置:StoreView(ids: ["product1", "product2"]) .storeViewStyle(.collection) .subscriptionGroupLabel("套餐选项")
6. 系统要求 #
ProductView | StoreView | |
---|---|---|
最低系统版本 | iOS 15.0+、macOS 12.0+ | iOS 17.0+、macOS 14.0+ |
何时选择? #
使用
ProductView
的情况- 只需展示单个商品。
- 需要快速集成购买功能,不追求复杂界面。
- 支持较低系统版本(iOS 15/macOS 12)。
使用
StoreView
的情况- 需要展示多个商品或订阅组。
- 希望自动管理订阅选项的展示和购买流程。
- 目标用户系统为 iOS 17/macOS 14 或更高。
混合使用示例 #
结合两者,实现灵活布局:
struct HybridStoreView: View {
var body: some View {
VStack {
// 用 StoreView 展示订阅组
StoreView(ids: ["subscription_monthly", "subscription_yearly"])
.subscriptionGroupLabel("订阅计划")
// 用 ProductView 展示独立商品
ProductView(id: "coins_100")
.productViewStyle(.compact)
}
}
}
总结 #
- 简单性 vs 全面性:
ProductView
轻量但功能单一,StoreView
复杂但覆盖多商品场景。 - 订阅场景优先:若涉及订阅,优先使用
StoreView
以利用其自动分组功能。 - 版本兼容性:考虑用户设备的系统版本,选择兼容的组件。