Ant*_*ton 5 alert mvvm ios swift swiftui
我正在尝试使用 SwiftUI 和 MVVM 架构构建一个应用程序。我想让我的视图在它的 ViewModel 认为有必要的时候显示一个警报——比如,当它有一个来自模型的新结果时。因此,假设每当 VM 检测到新结果时,它会status相应地设置:
视图模型:
enum Status {
case idle
case computing
case newResultAvailable
}
class MyViewModel: ObservableObject {
@Published var status = Status.idle
...
}
Run Code Online (Sandbox Code Playgroud)
风景:
struct ContentView: View {
@ObservedObject var vm = MyViewModel()
@State private var announcingResult = false {
didSet {
// reset VM status when alert is dismissed
if announcingResult == false {
vm.status = .idle
}
}
}
var body: some View {
Text("Hello")
.alert(isPresented: $announcingResult) {
Alert(title: Text("There's a new result!"),
message: nil,
dismissButton: .default(Text("OK")))
}
}
}
Run Code Online (Sandbox Code Playgroud)
Apple 将.alert()修饰符设计为将绑定作为其第一个参数,以便在绑定属性变为 时显示警报true。然后,当警报解除时,绑定属性会自动设置为false。
我的问题是:
当 VMstatus变为时,我怎样才能让警报出现.newResultAvailable?在我看来,这就是 MVVM 应该如何正确运行,这与所有 SwiftUI WWDC 演示的精神非常相似,但我找不到方法……
这是可能的方法(经过测试并与 Xcode 11.3+ 一起使用)
struct ContentView: View {
@ObservedObject var vm = MyViewModel()
var body: some View {
let announcingResult = Binding<Bool>(
get: { self.vm.status == .newResultAvailable },
set: { _ in self.vm.status = .idle }
)
return Text("Hello")
.alert(isPresented: announcingResult) {
Alert(title: Text("There's a new result!"),
message: nil,
dismissButton: .default(Text("OK")))
}
}
}
Run Code Online (Sandbox Code Playgroud)
有时,以下符号可能更可取
var body: some View {
Text("Hello")
.alert(isPresented: Binding<Bool>(
get: { self.vm.status == .newResultAvailable },
set: { _ in self.vm.status = .idle }
)) {
Alert(title: Text("There's a new result!"),
message: nil,
dismissButton: .default(Text("OK")))
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个助手类
class AlertProvider {
struct Alert {
var title: String
let message: String
let primaryButtomText: String
let primaryButtonAction: () -> Void
let secondaryButtonText: String
}
@Published var shouldShowAlert = false
var alert: Alert? = nil { didSet { shouldShowAlert = alert != nil } }
}
Run Code Online (Sandbox Code Playgroud)
在VM中它可以这样使用
var alertProvider = AlertProvider()
func showAlert() {
alertProvider.alert = AlertProvider.Alert(
title: "The Locatoin Services are disabled",
message: "Do you want to turn location on?",
primaryButtomText: "Go To Settings",
primaryButtonAction: { [weak self] in
self?.appSettingsHandler.openAppSettings()
},
secondaryButtonText: "Cancel"
)
}
Run Code Online (Sandbox Code Playgroud)
我们还可以使用 Alert View 类的扩展
extension Alert {
init(_ alert: AlertProvider.Alert) {
self.init(title: Text(alert.title),
message: Text(alert.message),
primaryButton: .default(Text(alert.primaryButtomText),
action: alert.primaryButtonAction),
secondaryButton: .cancel(Text(alert.secondaryButtonText)))
}
}
Run Code Online (Sandbox Code Playgroud)
然后视图会以下列方式使用它
.alert(isPresented: $viewModel.alertProvider.shouldShowAlert ) {
guard let alert = viewModel.alertProvider.alert else { fatalError("Alert not available") }
return Alert(alert)
}
Run Code Online (Sandbox Code Playgroud)
我相信这种方法可以进一步改进
| 归档时间: |
|
| 查看次数: |
2543 次 |
| 最近记录: |