SwiftUI提供了一个解决方案来呈现LocalizedError
func alert<E, A>(
isPresented: Binding<Bool>,
error: E?,
@ViewBuilder actions: () -> A
) -> some View where E : LocalizedError, A : View
您可以创建一个简单的enum
,它可以显示任何标准Error
或自定义错误.
enum LocalError: LocalizedError {
//Use for any built in error
case error(Error)
//Use for something custom
case invalidId
var errorDescription: String? {
switch self {
case .error(let error):
return error.localizedDescription
case .invalidId:
return "\(self)"
}
}
var recoverySuggestion: String? {
switch self {
case .error(let error):
let nsError = error as NSError
return nsError.localizedRecoverySuggestion
default:
return nil
}
}
}
然后,您可以修改进度枚举.
enum ProgressState {
case idle
case loading
case completed(Model)
case error(Error)
然后,您可以在该状态被触发时触发alert
(或工作表
switch state {
case .error(let error):
Text(state.stateName)
.task {
alert = (true, .error(error))
}
default :
Text(state.stateName)
}
以下是完整的代码.
import SwiftUI
struct FooView: View {
enum ProgressState {
case idle
case loading
case completed(Model)
case error(LocalError)
var stateName: String {
switch self {
case .completed(_):
return "Complete"
case .error(_):
return "Something went wrong"
default:
return "\(self)"
}
}
}
@State private var state: ProgressState = .idle
@State private var alert: (isPresented: Bool, error: LocalError?) = (false, nil)
var body: some View {
Group {
switch state {
case .error(let error):
Text(state.stateName)
.task {
alert = (true, error)
}
default :
Text(state.stateName)
}
}.alert(isPresented: $alert.isPresented, error: alert.error) {
Button("Ok") {
alert = (false, nil)
}
}
.task {
try? await Task.sleep(for: .seconds(1))
state = .error(.invalidId)
}
}
struct Model {
}
enum LocalError: LocalizedError {
//Use for any built in error
case error(Error)
//Use for something custom
case invalidId
var errorDescription: String? {
switch self {
case .error(let error):
return error.localizedDescription
case .invalidId:
return "\(self)"
}
}
var recoverySuggestion: String? {
switch self {
case .error(let error):
let nsError = error as NSError
return nsError.localizedRecoverySuggestion
default:
return nil
}
}
}
}
#Preview {
FooView()
}
这提供了一个独立的alert
变量,因此.alert
的表示不会与后面的View
冲突,也不会做出任何不安全的假设.