【问题标题】:I can't change TabBarViewController when I Have an assync request当我有异步请求时,我无法更改 TabBarViewController
【发布时间】:2019-01-28 16:11:18
【问题描述】:

在我提出请求并找到并填充我的对象之前,我无法更改视图。

我试图将我的代码与 GCD 异步。这不工作

override func viewDidLoad() {
    getHeartStroke()
NotificationCenter.default.addObserver(forName:NSNotification.Name("HeartStrokeNotification"), object: nil, queue: nil, using: notificationFinish)
 }

 func getHeartStroke() {
AF.request("http://localhost:8080/heartstroke", method: .get, headers: nil).responseJSON(completionHandler: {response in
    if (response.error == nil)
    {
        let json = JSON(response.result.value!)
            DispatchQueue.global(qos: .userInitiated).async {
                guard let hearstrokeArray = try? JSONDecoder().decode([HeartStroke].self, from: json.rawData()) else{
                    debugPrint("An error has occurred")
                    return
                }
                NotificationCenter.default.post(name:NSNotification.Name("HeartStrokeNotification"), object: hearstrokeArray, userInfo: nil)
            }
        }else{
            NotificationCenter.default.post(name:NSNotification.Name("HeartStrokeErrorNotification"), object: nil, userInfo: nil)
        }
    })
 }

 func notificationFinish(notification:Notification) -> Void{
  if (notification.name.rawValue == "HeartStrokeNotification"){

    arrayHeartstroke = notification.object as! [HeartStroke]
    DispatchQueue.main.async(execute: {
        self.tableView.reloadData()
    })
}

使用此代码,我会一直阻塞在我的页面上,直到 getHeartStroke() 结束,我希望在获取的同时在我的应用程序中导航。

【问题讨论】:

  • AF里面有什么代码???
  • 你为什么在这里使用通知?只需使用完成处理程序。
  • 您还应该在 viewDidLoad() 方法中调用 super.viewDidLoad()。

标签: swift grand-central-dispatch codable


【解决方案1】:

您需要一个完成处理程序来处理这个问题。使用通知中心只会让您的生活变得困难和复杂,并可能导致意外行为。下面是一些示例代码:

func getHeartStroke(completionHandler: (_ heartStroke: [HeartStroke?], _ error: NSError?) -> ()) {
    AF.request("http://localhost:8080/heartstroke", method: .get, headers: nil).responseJSON(completionHandler: {response in
        if (response.error == nil)
        {
            let json = JSON(response.result.value!)
            DispatchQueue.global(qos: .userInitiated).async {
                guard let hearstrokeArray = try? JSONDecoder().decode([HeartStroke].self, from: json.rawData()) else{
                    debugPrint("An error has occurred")
                    return
                }
                completionHandler(hearstrokeArray, nil)
            }
        } else {
            completionHandler(nil, response.error))
        }
    })
}

那么你可以这样称呼它:

getHeartStroke { [weak self] (heartStrokeArray, error) in
     guard let self = self else {return}
        if error != nil {
            self.processError(error)
        } else {
            self.processHeartStroke(heartStrokeArray)
        }
    }

processError 和 processHeartStroke 将是您应该创建的用于处理 heartStrokeArray 和错误对象的函数。

这些是标准回调或将函数传递给函数。您在网上找到的许多课程似乎都忽略了回调,但绝对值得您花时间学习它们。

您可以在此处了解有关闭包的更多信息(completionHandler 在这里命名):https://docs.swift.org/swift-book/LanguageGuide/Closures.html

【讨论】:

  • 好吧,这段代码肯定是异步工作的。直接在 AF 请求的最后一个括号之后,但在 getHeartStroke 函数中添加您的代码以移动到下一个视图。您需要做的就是确保视图设置为等待数据,而不是在实例化时需要它。从告诉我的情况来看,听起来您的问题出在下一个视图而不是此视图上,并且它们的方式是在实例化后立即需要数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
相关资源
最近更新 更多