swift 从视图模型中删除视图[MODAL PAGE]

tp5buhyn  于 5个月前  发布在  Swift
关注(0)|答案(3)|浏览(63)

我正在使用swiftUI和合并,我在我的虚拟机中有一些业务逻辑。一些结果必须驳回我的观点。
我在一些视图中使用了这个:

@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

self.presentationMode.wrappedValue.dismiss()

字符串
我想在我的视图模型中添加类似的内容。

nimxete2

nimxete21#

SwiftUI中,你不用命令式的方式来解除,而是通过将.sheet视图绑定到一个布尔属性来使用它,这个布尔属性将从上述视图模型中变异出来。

编辑:

在回答了question的后续问题后,我提出了一种不同的方法,如果实际上需要从模态表示的View本身内部进行消除,那么它会很好。
您可以通过实现自定义Publisher来实现这一点,它将使用.send()方法来允许您向订阅者发送特定值(在这种情况下,你的View),使用SwiftUIView协议上定义的onReceive(_:perform:)方法订阅您定义的自定义Publisher的输出流。在perform action闭包中,您将可以访问发布者的最新发布值,您将实际删除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()
            }
        }
    }
}

lqfhib0f

lqfhib0f2#

如果你想让它变得简单,那么只需在viewModel中创建一个名为goBack的Bool类型的@Published变量,并在任何时候将其更改为true,并且在视图中只需使用.onChange修饰符,如果更改时bool为true,则运行presentationMode.wrappedValue.dismiss()。

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()
         }
      }
  }
}

字符串

x3naxklr

x3naxklr3#

解决方案可以进一步简化。只需在模型中使用Void发布器。例如:

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()
        }
    }
}

字符串

相关问题