How to wait for a function to end on iOS/Swift, before starting the second one

后端 未结 3 1224
囚心锁ツ
囚心锁ツ 2020-12-09 11:21

I basically have to methods, which are being called in my viewDidLoad. The first one gets the user\'s search preferences and saves the preferences to variables at the top. A

相关标签:
3条回答
  • 2020-12-09 12:02

    You can use Swift closures! They are made for that.

    Please refer to the Apple guide: Closures

    Here's the code you need in your particular case.

    FinishedDownload is the closure. When getTheSearchLocationAndRange() is called, its code is executed until the completed() line which waits for all processes of the function to finish. Once the processes finish (downloads for example), completed() calls the closure which activates the code defined in getTheSearchLocationAndRange { () -> () in. Therefore, loadDataFromDatabase() is only called once getTheSearchLocationAndRange() has entirely finished executing and the data is present (not nil).

        var searchLocation = String()
        var searchLocationCoordinates = [String:Double]()
        var searchRange = Int()
        typealias FinishedDownload = () -> ()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            getTheSearchLocationAndRange()
        }
    
        func getTheSearchLocationAndRange(completed: FinishedDownload) {
    
               // Code for searching Location Range HERE
    
               completed()
        }
    
        getTheSearchLocationAndRange { () -> () in
            loadDataFromDatabase()
        }
    

    I hope this solved your issue and answered your question :)

    BTW, about the "leaving your GUI hanging" part, Alamofire takes automatically care of this for you. If you don't use Alamofire, then you will have to manually assign the asynchronous request to a background thread so your GUI doesn't become unresponsive.

    0 讨论(0)
  • 2020-12-09 12:15

    I wrote a demo project and posted it on GitHub that simulates handling an asynchronous network download. Take a look at DuncanMC/SwiftCompletionHandlers.

    Specifically look at the method asyncFetchImage(), which does almost exactly what this thread is talking about: Uses an asynchronous method internally, and takes a completion block that it calls once the asynchronous load is done.

    That is the general pattern you should use. Write a method that takes a completion block/closure. Internally, have that method call whatever asynchronous function it needs and then call your completion closure from inside the asynchronous method call's completion closure.

    The function asyncFetchImage looks like this:

    func asyncFetchImage(imageName imageName: String,
      completion: (
        image: UIImage?,
        status: String) -> ())
    {
      print("Entering \(#function)")
    
      //Simulate a network operation by waiting a few seconds before loading an image
      let nSecDispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3.0 * Double(NSEC_PER_SEC)))
      let queue = dispatch_get_main_queue()
      dispatch_after(nSecDispatchTime, queue)
        {
          () -> Void in
          let result = UIImage(named: imageName)
          print("Loading image in background")
          let status = result != nil ? "image loaded" : "Error loading image"
          print("About to call completion handler")
          completion(image: result, status: status)
      }
      print("Leaving \(#function)")
    }
    
    0 讨论(0)
  • 2020-12-09 12:16

    Okay I've found an solution. I basically called the function at the end of the first one.

    So basically:

        var searchLocation = String()
        var searchLocationCoordinates = [String:Double]()
        var searchRange = Int()
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Gets the user's search preference
            getTheSearchLocationAndRange()
        }
    
        func getTheSearchLocationAndRange() {
        // Code for getTheSearchLocationAndRange()
    
        loadDataFromDatabase()
        }
    
        func loadDataFromDatabase(){
        // Code for loadDataFromDatabase()
        }
    
    0 讨论(0)
提交回复
热议问题