从视图模型中取消视图[MODAL PAGE]

时间:2019-11-29 10:35:34

标签: swift swiftui combine

我正在使用swiftUI进行合并,我的VM中具有一些业务逻辑。有些结果不得不驳斥我的观点。

我在某些视图中使用过这个:

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

self.presentationMode.wrappedValue.dismiss()

我想要在视图模型中使用类似的东西。

1 个答案:

答案 0 :(得分:1)

您不会在SwiftUI中以命令方式进行解雇。取而代之的是,您通过将.sheet视图绑定到一个布尔属性来使用该视图,该布尔属性将从该视图模型中发生变化。

编辑:

  

在回答后续问题之后   question,   我想出了另一种方法。如果解雇是很不错的   实际上需要从模态呈现的View内部完成   本身。

您可以通过实现自定义Publisher来实现此目的,该自定义.send()将使用View方法来允许您将特定值发送给订户(在这种情况下为onReceive(_:perform:))。您将使用在 SwiftUI View协议上定义的Publisher方法来订阅您定义的自定义perform的输出流。在View动作闭包内,您将可以访问{{1}。

有足够的理论,您可以看一下下面的代码,应该不会很难理解:

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