SwiftUI:如何在按钮单击+ API 调用后显示下一个视图

Sch*_*ken 5 ios swift swiftui

这听起来像是一个微不足道的任务,但我找不到解决这个问题的正确方法。可能我还没有内化“SwiftUI-ish”的思维方式。

我有一个带有按钮的视图。当视图加载时,有一个条件(已经登录?),在该条件下视图应该直接转到下一个视图。如果单击该按钮,则会触发 API 调用(登录),如果成功,还会重定向到下一个视图。

我的尝试是建立一个模型(ObservableObject)来保存变量“shouldRedirectToUploadView”,它是一个 PassThroughObject。一旦满足视图中的 onAppear 条件或单击按钮(并且 API 调用成功),该变量就会翻转为 true 并告诉观察者更改视图。

翻转模型中的“shouldRedirectToUploadView”似乎有效,但我无法使视图重新评估该变量,因此新视图将无法打开。

这是到目前为止我的实现:

该模型

import SwiftUI
import Combine

class SboSelectorModel: ObservableObject {

    var didChange = PassthroughSubject<Void, Never>()

    var shouldRedirectToUpdateView = false {
        didSet {
            didChange.send()
        }
    }

    func fetch(_ text: String) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.shouldRedirectToUpdateView = true
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

风景

import SwiftUI

struct SboSelectorView: View {
    @State var text: String = ""
    @ObservedObject var model: SboSelectorModel

    var body: some View {
        return ZStack {
            if (model.shouldRedirectToUpdateView) {
                UpdateView()
            }
            else {
                Button(action: {
                    self.reactOnButtonClick()
                }) {
                    Text("Start")
                }
            }
        }.onAppear(perform: initialActions)
    }

    public func initialActions() {
        self.model.shouldRedirectToUpdateView = true
    }

    private func reactOnButtonClick() {
        self.model.fetch()
    }
}
Run Code Online (Sandbox Code Playgroud)

在旧的 UIKit 中,我只会使用 ViewController 来捕获按钮单击的操作,然后将新视图放在导航堆栈上。我该如何在 SwiftUI 中做到这一点?

在上面的示例中,我希望加载视图,执行onAppear()函数,该函数执行initialActions()来翻转模型变量,这将使视图对更改做出反应并呈现UploadView。为什么事情没有那样发生呢?

有这样的示例,例如以编程方式导航到 SwiftUI 中的新视图通过按下 Swift UI 按钮显示新视图如何在 SwiftUI 中使用 URLSession 发出请求后呈现视图?这表明相同的程序。然而它似乎对我不起作用。我错过了什么吗?

先感谢您!

krj*_*rjw 3

苹果已经推出了@Published它可以完成所有的model did change事情。

这对我有用,而且看起来干净多了。

当模型中的某些内容发生变化时,您还可以用来.onReceive()在视图上执行某些操作。

class SboSelectorModel: ObservableObject {
    @Published var shouldRedirectToUpdateView = false

    func fetch(_ text: String) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.shouldRedirectToUpdateView = true
        }
    }
}

struct UpdateView: View {
    var body: some View {
        Text("Hallo")
    }
}

struct SboSelectorView: View {
    @State var text: String = ""
    @ObservedObject var model = SboSelectorModel()

    var body: some View {
        ZStack {
            if (self.model.shouldRedirectToUpdateView) {
                UpdateView()
            }
            else {
                Button(action: {
                    self.reactOnButtonClick()
                }) {
                    Text("Start")
                }
            }
        }.onAppear(perform: initialActions)
    }

    public func initialActions() {
        self.model.shouldRedirectToUpdateView = true
    }

    private func reactOnButtonClick() {
        self.model.fetch("")
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助。

编辑

所以这似乎在beta 5中发生了变化

这是一个工作模型PassthroughSubject

class SboSelectorModel: ObservableObject {
    let objectWillChange = PassthroughSubject<Bool, Never>()


    var shouldRedirectToUpdateView = false {
        willSet {
            objectWillChange.send(shouldRedirectToUpdateView)
        }
    }

    func fetch(_ text: String) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            self.shouldRedirectToUpdateView = true
        }
    }
}
Run Code Online (Sandbox Code Playgroud)