简体   繁体   English

在SwiftUI中使用NavigationButton和服务器请求

[英]Use NavigationButton with a server request in SwiftUI

How can I make a NavigationButton to wait for the server response before going to the next view ? 如何在进入下一个视图之前使NavigationButton等待服务器响应?

I've tried something like this 我尝试过这样的事情

NavigationButton(destination: LogonView(),  onTrigger: { () -> Bool in
                    return self.viewModel.responseReceived
                }) {
                    Text("OK")
                    }.tapAction {
                        self.viewModel.fetch(companyID: &self.companyID)
                }

but the tapAction is never called. 但从未调用tapAction

I made it working using Button : 我用Button工作了:

Button(action: {
        self.viewModel.fetch(companyID: &self.companyID)
    }) {
        Text("OK")
    }.presentation(viewModel.shouldPresentModal ? Modal(LogonView() : nil)

    // in ViewModel
    var shouldPresentModal = false { // set to true when data are received from server
            didSet {
                didChange.send(())
            }
        }

but I need to show the next view in a navigation, not modally 但我需要在导航中显示下一个视图,而不是模态

Thank you! 谢谢!

Sorin, at least in my understanding SwiftUI is designed only for the presentation layer, it's not supposed to replace your model. 索林,至少在我的理解中,SwiftUI只是为表示层设计的,它不应该取代你的模型。 And it's "reactive", unlike UIKit, so making the view perform model-like actions is, by design, very hard. 与UIKit不同,它是“反应性的”,因此,通过设计,使视图执行类似模型的操作非常困难。

I would approach the task like this : 我会像这样接近任务:

class LoginModel : BindableObject {

    var didChange = PassthroughSubject<LoginModel, Never>()

    private(set) var username: String? {
        didSet {
            didChange.send(self)
        }
    }

    func load() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            self.username = "Sorin"
        }
    }
}

This is the model object encapsulating our login code. 这是封装我们的登录代码的模型对象。 The async operation is here simulated by a simple delay. 这里的异步操作是通过简单的延迟来模拟的。

And, then, the view : 然后,观点:

public struct LoginScreen: View {

    @ObjectBinding var loginObject = LoginModel()

    public var body: some View {
        Group {
            if login.username == nil {
                Text("Trying to login, please wait...")
            } else {
                Text("Successful login, the username is \(loginObject.username!)")
            }
        }.onAppear {
            self.loginObject.load()
        }
    }
}

There are better ways of "linking" with the model object, but we're looking here only at a bare-bone example, obviously. 有更好的方法可以“链接”模型对象,但我们现在只是在一个愚蠢的例子中看到这一点。

Your NavigationButton will only link to the LoginScreen, without any other code or trigger. 您的NavigationButton只会链接到LoginScreen,而不会有任何其他代码或触发器。 The screen will initially display Trying to login, please wait... and after 5 sec will change to Successful login, the username is Sorin . 屏幕最初将显示Trying to login, please wait...并且在5秒后将更改为Successful login, the username is Sorin Obviously you could go wild and replace my text here with anything you may want. 显然你可以疯狂地用你想要的任何东西替换我的文字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM