简体   繁体   中英

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.

  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?
  2. Then by pressing button Unhide/Animate indicator
  3. Make a server request via my rest api service
  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. 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.

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"

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. You can use as many of these Bool as you need. You can toggle a new view, 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. You can find some really cool animations:

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

You can find many animations here:

https://lottiefiles.com

And you can create a class to implement your Lottie animation via a JSON file that you dropped in your project:

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:

// 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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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