You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何等待API请求完成后再执行Segue跳转?

问题

我是Swift新手,目前遇到一个问题:点击按钮时想先从API请求数据,把获取到的数据传递给另一个视图控制器后再执行Segue跳转。但现在点击按钮后,请求刚启动就直接跳转到第二个视图控制器,根本没携带任何数据。

如何等待videoManager.performRequest(with: videoLinkTextField.text!)执行完成后再执行Segue?

当前按钮代码

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

当前prepare函数

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

当前performRequest函数

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()
}
解决方案

核心问题是performRequest是异步网络请求,你现在是请求刚发出去就立刻执行Segue,这时候数据还没回来。要解决这个,得把Segue的触发时机放在请求完成的回调里。

步骤1:移除按钮里的Segue调用

修改按钮点击方法,删掉直接调用performSegue的代码,只保留请求触发:

@IBAction func getVideoButtonPressed(_ sender: UIButton) {
    guard let link = videoLinkTextField.text, link.contains("tiktok") else {
        videoLinkTextField.text = ""
        let alert = UIAlertController(title: "错误", message: "请输入有效的链接", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default))
        present(alert, animated: true)
        return
    }
    // 只触发请求,不立即跳转
    videoManager.performRequest(with: link)
}

步骤2:在代理回调里触发Segue

你的videoManager用了代理模式,在didUpdateVideo回调(数据请求成功并解析完成时触发)里调用Segue:
假设当前视图控制器已遵守VideoManagerDelegate,实现以下方法:

extension YourViewController: VideoManagerDelegate {
    func didUpdateVideo(_ manager: VideoManager, video: Video) {
        // 把解析后的视频数据赋值给当前控制器的videoUrl
        self.videoUrl = video.url // 根据你的Video模型实际字段调整
        // 回到主线程触发Segue(网络回调在后台线程,UI操作必须在主线程)
        DispatchQueue.main.async {
            self.performSegue(withIdentifier: "GoToVideo", sender: self)
        }
    }

    func didFailedWithError(_ error: Error) {
        // 请求失败时弹提示
        DispatchQueue.main.async {
            let alert = UIAlertController(title: "请求失败", message: error.localizedDescription, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            self.present(alert, animated: true)
        }
    }
}

步骤3:优化prepare函数

prepare方法本身就在主线程执行,不需要再套DispatchQueue.main.async,直接赋值即可:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard segue.identifier == "GoToVideo",
          let destinationVC = segue.destination as? ResultViewController else {
        return
    }
    // 此时videoUrl已经有值了,直接传递
    destinationVC.videoUrl = self.videoUrl
    print("传递的视频链接:\(self.videoUrl ?? "无数据")")
}

额外建议

  • 避免强制解包(!),尽量用guard let或if let处理可选值,减少崩溃风险
  • 网络请求的URL最好做百分号编码,避免链接里有特殊字符导致请求失败:
    if let encodedUrl = videoUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
       let requestUrl = URL(string: "https://tiktok-downloader-download-videos-without-watermark1.p.rapidapi.com/media-info/?link=\(encodedUrl)") {
        // 使用requestUrl创建请求
    }
    

内容的提问来源于stack exchange,提问作者themmfa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:40:29