当服务器回调时,按下 SwiftUI 按钮并转到下一个屏幕(下一个视图)

Mat*_*der 1 swift swift5 swiftui

当我想按下按钮显示加载指示器并且如果服务器返回成功响应则显示新视图时,我坚持了非常简单的步骤

在 UIKit 中这非常简单,但在 SwiftUI 中我坚持这样做。

  1. 我需要知道如何初始化/添加活动指示器我在这里找到了一些很酷的例子。我可以将它作为 let 变量存储在我的视图结构中吗?
  2. 然后按“取消隐藏/动画指示器”按钮
  3. 通过我的rest api 服务发出服务器请求
  4. 等待一段时间,然后在成功回调或错误消息上显示新视图。

没什么超级难的,但我卡在这里的是一个按钮,它是我的导航视图的一部分。请帮我推到新屏幕。

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

    })
Run Code Online (Sandbox Code Playgroud)

我找到了一些链接,但不确定如何正确使用它。

不确定我需要PresentationButtonNavigationLink根本不知道,因为我已经有一个简单的按钮并且想要推送新的视图控制器。

与此问题非常相似的问题,但我没有发现它有用,因为我不知道如何逐步使用如何“创建隐藏的 NavigationLink 并绑定到该状态”

编辑: 我还发现这个视频答案看起来像我弄清楚如何进行导航。但仍需要弄清楚如何在按下按钮时显示活动指示器。

Rol*_*tte 5

要在 SwiftUI 中的某个时刻显示您需要的任何内容,只需使用@State变量即可。您可以根据需要使用任意数量的 Bool。您可以切换新视图、动画...

例子

@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
  }
}
Run Code Online (Sandbox Code Playgroud)

至于动画,我建议使用Lottie框架。您可以找到一些非常酷的动画:

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

您可以在这里找到许多动画:

https://lottiefiles.com

您可以创建一个类,通过放入项目中的 JSON 文件来实现 Lottie 动画:

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) { }
}
Run Code Online (Sandbox Code Playgroud)

创建一个 SwiftUI 文件以在代码中使用 Lottie 动画:

// 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)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,最终的代码看起来像这样,带有一个 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
    }
  }
}
Run Code Online (Sandbox Code Playgroud)