简体   繁体   English

服务器回调时按 SwiftUI 按钮和 go 到下一个屏幕(下一个视图)

[英]Press SwiftUI button and go to the next screen (next view) when server callback

I stuck at the pretty simple step when I want to press on the button show loading indicator and if server returns success response then show new view当我想按下按钮显示加载指示器并且如果服务器返回成功响应然后显示新视图时,我停留在非常简单的步骤

It's pretty straightforward in UIKit, but with SwiftUI I stuck to do this.在 UIKit 中它非常简单,但在 SwiftUI 中我坚持这样做。

  1. I need to know how to init/add activity indicator I found some cool examples here .我需要知道如何初始化/添加活动指示器我在这里找到了一些很酷的示例。 Can I just store it as a let variable in my view sruct?我可以将它作为 let 变量存储在我的视图结构中吗?
  2. Then by pressing button Unhide/Animate indicator然后按按钮取消隐藏/动画指示器
  3. Make a server request via my rest api service通过我的 rest api 服务发出服务器请求
  4. Wait some time and show new view on success callback or error message.等待一段时间并显示有关成功回调或错误消息的新视图。

Nothing super hard, but I stuck here is a button which is a part of my NavigationView.没什么特别难的,但我卡在这里的是一个按钮,它是我的 NavigationView 的一部分。 Please help me push to new screen.请帮我推到新屏幕。

    Button(action: {
     // show indicator or animate
     // call rest api service
     // wait for callback and show next view or error alert

    })

I found some link but not sure how to use it right.我找到了一些链接,但不知道如何正确使用它。

Not sure I need PresentationButton or NavigationLink at all as I already have a simple Button and want to kind of push new view controller.不确定我是否需要PresentationButtonNavigationLink ,因为我已经有一个简单的 Button 并且想要推送新视图 controller。

Very similar question to this one but I have not find it useful as I don't know how to use step by step how to "Create hidden NavigationLink and bind to that state"这个问题非常相似,但我发现它没有用,因为我不知道如何逐步使用如何“创建隐藏的 NavigationLink 并绑定到该状态”

EDITED: I also found this video answer looks like I figure out how to do navigation.已编辑:我还发现这个视频答案看起来像是我知道如何进行导航。 But still need to figure out how to show activity indicator when button pressed.但是仍然需要弄清楚按下按钮时如何显示活动指示器。

To show anything you need at some point in SwiftUI, simply use a @State variable.要在 SwiftUI 中的某个时间点显示您需要的任何内容,只需使用 @State 变量。 You can use as many of these Bool as you need.您可以根据需要使用任意数量的这些 Bool。 You can toggle a new view, animation...您可以切换一个新视图,animation...

example:例子:

@State var showNextView = false
@State var showLoadingAnimation = false

Button(action: {
  self.showLoadingAnimation.toggle()
  self.makeApiCall()
}) {
  Text("Show next view on api call success")
}

// Method that handle your api call
func makeApiCall() {
  // Your api call
  if success {
    showLoadingAnimation = false
    showNextView = true
  }
}

As for the animation, I would suggest you use the Lottie framework.至于 animation,我建议你使用 Lottie 框架。 You can find some really cool animations:你可以找到一些非常酷的动画:

https://github.com/airbnb/lottie-ios https://github.com/airbnb/lottie-ios

You can find many animations here:你可以在这里找到很多动画:

https://lottiefiles.com https://lottiefiles.com

And you can create a class to implement your Lottie animation via a JSON file that you dropped in your project:您可以创建一个 class 来通过您在项目中放置的 JSON 文件来实现您的 Lottie animation:

import SwiftUI
import Lottie

struct LottieRepresentable: UIViewRepresentable {

  let named: String // name of your lottie file
  let loop: Bool

  func makeUIView(context: Context) -> UIView {
    let view = UIView(frame: .zero)

    let animationView = AnimationView()
    let animation = Animation.named(named)
    animationView.animation = animation
    animationView.contentMode = .scaleAspectFit
    if loop { animationView.loopMode = .loop }
    animationView.play()

    animationView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(animationView)

    NSLayoutConstraint.activate([
      animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
      animationView.heightAnchor.constraint(equalTo: view.heightAnchor)
    ])

    return view
  }

  func updateUIView(_ uiView: UIView, context: Context) { }
}

Create a SwiftUI file to use your lottie animation in your code:创建一个 SwiftUI 文件以在您的代码中使用您的乐天 animation:

// MARK: - Show LottieRespresentable as view
struct LottieView: View {

  let named: String
  let loop: Bool
  let size: CGFloat

  var body: some View {
    VStack {
      LottieRepresentable(named: named, loop: loop)
        .frame(width: size, height: size)
    }
  }
}

So the final code would look like this with a NavigationLink, and you will have your loader starting at the beginning of your api call, and ending when api call succeeds:所以最终的代码看起来像这样带有 NavigationLink,你的加载器将从 api 调用的开头开始,并在 api 调用成功时结束:

import SwiftUI

//MARK: - Content view
struct ContentView: View {

  @State var showMessageView = false
  @State var loopAnimation = false

  var body: some View {
    NavigationView {
      ZStack {
        NavigationLink(destination: MessageView(),
                       isActive: $showMessageView) {
          Text("")

          VStack {
            Button(action: {
              self.loopAnimation.toggle()
              self.makeApiCall()
            }) {
              if self.loopAnimation {
                Text("")
              }
              else {
                Text("Submit")
              }
            }
          }

          if self.loopAnimation {
            LottieView(named: "Your lottie json file name",
                       loop: self.loopAnimation,
                       size: 50)
          }
        }
        .navigationBarTitle("Content View")
      }
    }
  }

  func makeApiCall() {
    // your api call
    if success {
      loopAnimation = false
      showMessageView = true
    }
  }
}

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

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