SwiftUI中如何通过SKStoreProductViewController加载App Store商品并以Sheet展示
问题根源
你当前的写法会导致两次弹窗:SwiftUI的sheet先弹出一个空白视图,之后调用openAppStore又手动present了SKStoreProductViewController,所以才会出现先空白页再显示App Store页面的重复弹窗问题。
解决方案
把SKStoreProductViewController包装成SwiftUI可直接使用的UIViewControllerRepresentable组件,直接作为Sheet的内容展示,避免手动二次弹窗。
1. 编写App Store页面的SwiftUI包装组件
import SwiftUI import StoreKit struct AppStoreProductView: UIViewControllerRepresentable { let productID: Int @Binding var isPresented: Bool func makeUIViewController(context: Context) -> SKStoreProductViewController { let vc = SKStoreProductViewController() vc.delegate = context.coordinator // 传入App ID参数加载页面 let parameters = [SKStoreProductParameterITunesItemIdentifier: productID] vc.loadProduct(withParameters: parameters) { _, error in // 加载失败时自动关闭Sheet并打印错误 if let error = error { print("App Store页面加载失败: \(error.localizedDescription)") self.isPresented = false } } return vc } func updateUIViewController(_ uiViewController: SKStoreProductViewController, context: Context) {} // 处理UIKit的代理回调 func makeCoordinator() -> Coordinator { Coordinator(parent: self) } class Coordinator: NSObject, SKStoreProductViewControllerDelegate { let parent: AppStoreProductView init(parent: AppStoreProductView) { self.parent = parent } // 关闭页面时同步SwiftUI的状态 func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) { parent.isPresented = false } } }
2. 修改ContentView使用包装组件
import SwiftUI struct ContentView: View { @State private var showAppStore = false // 替换成你的App Store产品ID private let appProductID = xxxxxxxxx var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) .onTapGesture { showAppStore.toggle() } // 直接在Sheet中展示包装好的App Store页面 .sheet(isPresented: $showAppStore) { AppStoreProductView(productID: appProductID, isPresented: $showAppStore) } } .padding() } } #Preview { ContentView() }
说明
- 这种写法直接将
SKStoreProductViewController作为Sheet的内容,彻底避免了重复弹窗的问题 - 通过
Coordinator同步UIKit的关闭事件到SwiftUI的状态变量,保证页面状态一致 - 新增了加载失败的处理逻辑,避免用户停留在空白页
内容的提问来源于stack exchange,提问作者piro299
相关产品推荐
相关产品推荐

