Home > Enterprise >  Wait Until Function Completes and Segue
Wait Until Function Completes and Segue

Time:10-01

Swift is new for me and I stuck at this part. I want to request some data from api when I clicked the button. After that, want to pass the data i get from this function to another view controller. So basicly want to perform segue with this data. However, when I clicked the button, request starts but it directly perform segue to 2. view without any data.

How can I wait for:

videoManager.performRequest(with: videoLinkTextField.text!)

this function to perform segue?

This is my button:

@IBAction func getVideoButtonPressed(_ sender: UIButton) {
    if videoLinkTextField.text != nil, videoLinkTextField.text!.contains("tiktok") {
        videoManager.performRequest(with: videoLinkTextField.text!)
        DispatchQueue.main.async {
            self.performSegue(withIdentifier: "GoToVideo", sender: self)
        }

    } else {
        videoLinkTextField.text = ""
        let alert = UIAlertController(title: "Error", message: "Please enter a valid link", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .default))
        present(alert, animated: true, completion: nil)
    }
}

Here is my prepare function:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "GoToVideo" {
        DispatchQueue.main.async {
            let destionationVC = segue.destination as! ResultViewController
            print("Test \(self.videoUrl)")
            destionationVC.videoUrl = self.videoUrl
        }
    }
}

And here is my performRequest function:

func performRequest(with videoUrl: String) {
    let request = NSMutableURLRequest(url: NSURL(string: "https://tiktok-downloader-download-videos-without-watermark1.p.rapidapi.com/media-info/?link=\(videoUrl)")! as URL,
                                      cachePolicy: .useProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.httpMethod = "GET"
    request.allHTTPHeaderFields = headers

    let session = URLSession.shared
    let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { data, _, error in
        if error != nil {
            self.delegate?.didFailedWithError(error!)
        }
        if let safeData = data {
            if let video = self.parseJSON(safeData) {
                self.delegate?.didUpdateVideo(self, video: video)
            }
        }
    })
    dataTask.resume()
}

CodePudding user response:

You are asking:

How can I wait for: videoManager.performRequest(with: videoLinkTextField.text!)

Looks like you may want to use a closure for this method: Check out this article to learn more about closures:

Escaping Closures in Swift

However, I'll also provide you an example of how you'd might want your function to look:

Note, I only added , completion: @escaping () -> Void as a param and added a completion() to indicate where the closure should finish (You can also pass params in a completion block too (e.g: String, Error, etc)

func performRequest(with videoUrl: String, completion: @escaping () -> Void) {
let request = NSMutableURLRequest(url: NSURL(string: "https://tiktok-downloader-download-videos-without-watermark1.p.rapidapi.com/media-info/?link=\(videoUrl)")! as URL,
                                  cachePolicy: .useProtocolCachePolicy,
                                  timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { data, _, error in
    if error != nil {
        self.delegate?.didFailedWithError(error!)
    }
    if let safeData = data {
        if let video = self.parseJSON(safeData) {
            self.delegate?.didUpdateVideo(self, video: video)
        }
    }
    completion() // finishes the closure
})
dataTask.resume()

}

Then you'll be able to do this:

videoManager.performRequest(with: videoLinkTextField.text!) { _ in
    DispatchQueue.main.async {
        self.performSegue(withIdentifier: "GoToVideo", sender: self)
    }
}

CodePudding user response:

Place segue here

if let video = self.parseJSON(safeData) {
   self.delegate?.didUpdateVideo(self, video: video)
   DispatchQueue.main.async {
     self.performSegue(withIdentifier: "GoToVideo", sender: self)
   }
 }
  • Related