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()
}
}
}
}
class ViewModel: ObservableObject {
@Published var goBack: Bool = false
fun itWillToggleGoBack() {
goBack.toggle()
}
}
struct MyView {
@StateObject var vm = ViewModel()
@Environment(\.presentationMode) var presentationMode
var body: some View {
Text("Any kind of view")
.onChange(of: vm.goBack) { goBack in
if goBack {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
class MyModel: ObservableObject {
private(set) var actionExecuted = PassthroughSubject<Void,Never>()
func execute() {
actionExecuted.send()
}
}
class MyView: View {
@Environment(\.dismiss) var dismiss
@StateObject var model = MyModel()
var body: some View {
Text("Hi")
.onReceive(model.actionExecuted) {
dismiss()
}
}
}
3条答案
按热度按时间nimxete21#
在
SwiftUI
中,你不用命令式的方式来解除,而是通过将.sheet
视图绑定到一个布尔属性来使用它,这个布尔属性将从上述视图模型中变异出来。编辑:
在回答了question的后续问题后,我提出了一种不同的方法,如果实际上需要从模态表示的
View
本身内部进行消除,那么它会很好。您可以通过实现自定义
Publisher
来实现这一点,它将使用.send()
方法来允许您向订阅者发送特定值(在这种情况下,你的View
),使用SwiftUI的View
协议上定义的onReceive(_:perform:)
方法订阅您定义的自定义Publisher
的输出流。在perform
action闭包中,您将可以访问发布者的最新发布值,您将实际删除View
。理论够了,可以看看代码,应该不会很难遵循,如下:
字符串
而同行的看法是:
型
老答案:
关于视图模型中的业务逻辑更改,一个非常简单的视图解除实现是:
型
lqfhib0f2#
如果你想让它变得简单,那么只需在viewModel中创建一个名为goBack的Bool类型的@Published变量,并在任何时候将其更改为true,并且在视图中只需使用.onChange修饰符,如果更改时bool为true,则运行presentationMode.wrappedValue.dismiss()。
字符串
x3naxklr3#
解决方案可以进一步简化。只需在模型中使用Void发布器。例如:
字符串