下面是苹果公司的股票请求退款逻辑,来自Food Truck Building a SwiftUI Multiplatform App,我正在尝试修改它以捕获退款请求错误。苹果似乎并不认为展示如何捕获与其示例逻辑相关的错误很重要,这使得像我这样仍在学习如何处理错误的人变得困难。
我在结果中看到以下错误,其中评论说在此处捕获退款错误。如果退款成功,则单一案例声明会解除控制。
这是我在各种打印声明中看到的:
退款错误绑定
(交易:SwiftUI.Transaction(plist:[]),位置:SwiftUI.StoredLocation >,_value:nil) 失败(StoreKit.Transaction.RefundRequestError.duplicateRequest) Transaction.RefundError 退款请求错误
所以我的问题是如何将错误的本地化描述(在本例中为重复请求)放入警报中?
部分问题似乎是在成功案例分支后出现的错误,而没有使用 do / catch 块。我尝试过使用错误来存储并在警报和gotError中使用,但我不知道结果类型。
感谢您的协助!
struct RefundView: View {
@State private var recentTransactions: [StoreKit.Transaction] = []
@State private var selectedTransactionID: UInt64?
@State private var refundSheetIsPresented = false
@State private var error: Error?
@State private var refundError: Bool = false
@State var gotError: String = ""
@Environment(\.dismiss) private var dismiss
var body: some View {
List(recentTransactions, selection: $selectedTransactionID) { transaction in
TransactionRowView(transaction: transaction)
}
.safeAreaInset(edge: .bottom) {
VStack(spacing: 0) {
Text("Select a purchase to refund")
.font(.subheadline)
.foregroundColor(.secondary)
.padding()
Button {
refundSheetIsPresented = true
} label: {
Text("Request a refund")
.bold()
.padding(.vertical, 5)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.padding([.horizontal, .bottom])
.disabled(selectedTransactionID == nil)
}
}
.task { @MainActor in
for await transaction in StoreKit.Transaction.all {
recentTransactions.append(transaction.unsafePayloadValue)
}
}
.refundRequestSheet(
for: selectedTransactionID ?? 0,
isPresented: $refundSheetIsPresented
) { result in
if case .success(.success) = result {
dismiss()
}
// ******* catch refund errors here *******
self.error = error
refundError.toggle()
// $gotError = result
print("refund error \($error)")
print(result)
print("Transaction.RefundError \(Transaction.RefundRequestError)")
}
.navigationTitle("Refund Purchase")
.alert("Refund error: \(gotError)", isPresented: $refundError, actions: {})
}
}
本例中的
result
是 Result<Transaction.RefundRequestStatus, Transaction.RefundRequestError>
,而您的 gotError
变量是 String
,所以它不等价。您也不需要前缀 $
。该符号用于读写绑定。
if case .success(.success) = result {
dismiss()
}
self.error = error
refundError.toggle()
通过像上面这样写,你是说在任何情况下:成功或失败,
refundError
属性将始终切换,这会导致:
部分问题似乎是在成功案例之后出现错误
您可以通过将
result
分为两种情况来修复它,正如 @lorem 在他的评论中所说。然后仅更改 refundError = true
,因为它是一个 @State 对象并与 .alert(isPresented:)
链接。当警报解除时,它会自动返回到false
。
swift result {
case .success(let state):
if state == .success {
dismiss()
}
case .failure(let storeKitError):
self.error = storeKitError
self.refundError = true
}
最后,您不必在这里使用另一个
@State var gotError: String
,因为您已经存储了error
。因此,我建议使用计算属性来获取错误本地化描述。
private var gotError: String {
error?.localizedDescription ?? ""
}
...
.alert("Refund error: \(gotError)", isPresented: $refundError, actions: {})