【问题标题】:Swift UITableView reloadData in a closureSwift UITableView reloadData 在一个闭包中
【发布时间】:2014-12-04 07:43:20
【问题描述】:

我相信我遇到了一个问题,即我的关闭发生在后台线程上,并且我的 UITableView 更新速度不够快。我正在调用 REST 服务,在我的关闭中我有一个 tableView.reloadData() 调用,但这需要几秒钟才能发生。如何使数据重新加载更快(可能在主线程上?)

REST 查询函数 - 使用 SwiftyJSON 库进行解码

func asyncFlightsQuery() {
    var url : String = "http://127.0.0.1:5000/flights"
    var request : NSMutableURLRequest = NSMutableURLRequest()
    request.URL = NSURL(string: url)
    request.HTTPMethod = "GET"

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{ (response:NSURLResponse!, networkData: NSData!, error: NSError!) -> Void in
        var error: AutoreleasingUnsafeMutablePointer<NSError?> = nil


        // Parse with SwiftyJSON
        let json = JSON(data: networkData)

        // Empty out Results array
        self.resultArray = []

        // Populate Results Array
        for (key: String, subJson: JSON) in json["flights"] {
            print ("KEY: \(key) ")
            print (subJson["flightId"])
            print ("\n")

            self.resultArray.append(subJson)
        }

        print ("Calling reloadData on table..??")
        self.tableView.reloadData()


    })
}

一旦在我的调试器中调用了self.tableView.reloadData()

【问题讨论】:

    标签: ios swift uitableview reloaddata


    【解决方案1】:

    UIKit 不是线程安全的。 UI 只能从主线程更新:

    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
    

    更新。在 Swift 3 及更高版本中使用:

    DispatchQueue.main.async {
        self.tableView.reloadData()
    }
    

    【讨论】:

    • 正确的代码应该是:dispatch_async(dispatch_get_main_queue(), {self.tableView.reloadData()})
    • 抱歉,已修复。
    • 我们不应该使用 [weak self] 代替 self 来避免保留循环吗?
    • @G.Abhisek 不需要,因为 dispatch_async 永远不会捕获捕获强自我的块。
    • @G.Abhisek dispatch_async 只会保留保留self 的块,直到块被执行。此外,调用dispatch_async 的代码不包含对其内部的任何引用,因此不存在保留周期的风险。
    【解决方案2】:

    你也可以像这样重新加载UITableView

    self.tblMainTable.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true)
    

    【讨论】:

    • 这个函数应该放在哪里?在 viewdidload 中?
    【解决方案3】:

    您还可以使用NSOperationQueue.mainQueue() 更新主线程。对于多线程,NSOperationQueue 是一个很棒的工具。

    一种写法:

    NSOperationQueue.mainQueue().addOperationWithBlock({
         self.tableView.reloadData()       
    })
    

    更新DispatchQueue is the way to go for this

    更新 2Use DispatchQueue solution as seen in accepted answer above

    【讨论】:

      【解决方案4】:

      使用 Swift 3 使用

      DispatchQueue.main.async {
          self.tableView.reloadData()
      }
      

      【讨论】:

      • 这会冻结 UI 吗?
      • 不,这不会冻结 UI。
      【解决方案5】:

      SWIFT 3:

      OperationQueue.main.addOperation ({
           self.tableView.reloadData()
      })
      

      【讨论】:

        【解决方案6】:
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
        

        执行此操作以更新主线程上的 UI。使用此方法,它将更新表格视图并在 UI 中反映数据。

        【讨论】:

          【解决方案7】:

          我建议进一步改进它(从 swift 3 开始):

          struct UIHelper {
              static func performUpdate(using closure: @escaping () -> Void) {
                  if Thread.isMainThread {
                      closure()
                  } else {
                      DispatchQueue.main.async(execute: closure)
                  }
              }
          }
          

          然后:

          UIHelper.performUpdate {
              self.tableView.reloadTable()
          }
          

          原因是有时调用是在主线程上进行的,所以不需要在异步线程上执行 UI 更新。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-11-04
            • 2017-02-11
            • 2016-04-05
            • 1970-01-01
            • 1970-01-01
            • 2011-02-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多