ProductView renders one purchasable product, loading and purchase flow included, from a single
line. StoreView lays out a collection of them. Both ship with StoreKit 2's SwiftUI layer.
ProductView
One product id is enough. Styles come through productViewStyle: automatic (default),
large, regular, or compact.
ProductView(id: "55667744")
.productViewStyle(.compact)
prefersPromotionalIcon: true shows the promoted image uploaded to App Store Connect. An
initializer overload swaps in your own icon view, with a placeholder while the product loads.
ProductView(id: "55667744") { _ in
Image(systemName: "crown")
.resizable()
.scaledToFit()
} placeholderIcon: {
ProgressView()
}
.productViewStyle(.large)
Custom Styles
Conform to ProductViewStyle for a fully custom presentation. makeBody receives a
configuration carrying the loading state, the product, and a purchase() function to call from
your own button.
struct CustomProductStyle: ProductViewStyle {
func makeBody(configuration: Configuration) -> some View {
switch configuration.state {
case .loading:
ProgressView()
case .success(let product):
Button {
configuration.purchase()
} label: {
VStack {
Text(verbatim: product.displayName).font(.headline)
Text(verbatim: product.displayPrice)
}
}
.buttonStyle(.borderedProminent)
default:
Text("Something goes wrong...")
}
}
}
The rendered views handle purchasing and observe refunds automatically; you compose layout, not transaction plumbing.
StoreView
StoreView(ids:) displays several products at once and adapts its layout to the platform, a
grid on tvOS for example. The productViewStyle modifier still applies, and storeButton
toggles the built-in buttons such as restore purchases.
StoreView(ids: ["123456789", "987654321"])
.productViewStyle(.compact)
.storeButton(.visible, for: .restorePurchases)