您不会在 SwiftUI 中以命令式的方式进行解雇。相反,您可以通过将 .sheet 视图绑定到一个布尔属性来使用它,该属性将从该视图模型中发生变异。
编辑:
回答后续问题后
question,
我想出了一个不同的方法。如果解雇是很好的
实际上需要从模态呈现的View 内部完成
自己。
您可以通过实现您的自定义Publisher 来实现这一点,它将使用.send() 方法允许您向订阅者发送特定值(在本例中为您的View)。您将使用 SwiftUI 的 View 协议上定义的 onReceive(_:perform:) 方法订阅您定义的自定义 Publisher 的输出流。在perform 操作闭包中,您可以访问发布者的最新发出值,您将实际解除View。
理论说的够多了,可以看代码,应该不难理解,如下:
import Foundation
import Combine
class ViewModel: ObservableObject {
var viewDismissalModePublisher = PassthroughSubject<Bool, Never>()
private var shouldDismissView = false {
didSet {
viewDismissalModePublisher.send(shouldDismissView)
}
}
func performBusinessLogic() {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.shouldDismissView = true
}
}
}
和视图对应的是:
import SwiftUI
struct ContentView: View {
@State private var isDetailShown = false
var body: some View {
VStack {
Text("Hello, World!")
Button(action: {
self.isDetailShown.toggle()
}) {
Text("Present Detail")
}
}
.sheet(isPresented: $isDetailShown) {
DetailView()
}
}
}
struct DetailView: View {
@ObservedObject var viewModel = ViewModel()
@Environment(\.presentationMode) private var presentationMode
var body: some View {
Text("Detail")
.navigationBarTitle("Detail", displayMode: .inline)
.onAppear {
self.viewModel.performBusinessLogic()
}
.onReceive(viewModel.viewDismissalModePublisher) { shouldDismiss in
if shouldDismiss {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
旧答案:
关于视图模型中业务逻辑更改的视图关闭的一个非常简单的实现是:
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
Text("Hello, World!")
// the animation() modifier is optional here
.sheet(isPresented: $viewModel.isSheetShown.animation()) {
Text("Sheet Presented")
}
// From here - for illustration purpose
.onAppear {
self.viewModel.perform()
}
// To here
}
}
class ViewModel: ObservableObject {
@Published var isSheetShown = false
func perform() {
// this just an example. In real application, you will be responsible to
// toggle between the states of the `Bool` property
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.isSheetShown.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.isSheetShown.toggle()
}
}
}
}