获取数据和加载到UITableView之间的时间延迟是多少 [英] What is the time delay between getting data and loading to UITableView

查看:74
本文介绍了获取数据和加载到UITableView之间的时间延迟是多少的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过Api调用加载我的UITableView,但是尽管可以很快地检索到数据,但是在将数据加载到表中之前要花费大量的时间.使用的代码如下

import UIKit

class TrackingInfoController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var table : UITableView?
@IBOutlet var indicator : UIActivityIndicatorView?
@IBOutlet var spinnerView : UIView?

var tableArrayList = Array<TableData>()

struct TableData
{
    var dateStr:String = ""
    var nameStr:String = ""
    var codeStr:String = ""
    var regionStr:String = ""

    init(){}
}

override func viewDidLoad() {
    super.viewDidLoad()

    table!.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    spinnerView?.hidden = false
    indicator?.bringSubviewToFront(spinnerView!)
    indicator!.startAnimating()
    downloadIncidents()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

@IBAction func BackToMain() {
    performSegueWithIdentifier("SearchToMainSegue", sender: nil)
}

//#pragma mark - Table view data source

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1     //BreakPoint 2
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return tableArrayList.count;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell

    cell.incidentDate.text = tableArrayList[indexPath.row].dateStr
    cell.incidentText.text = tableArrayList[indexPath.row].nameStr
    cell.incidentCode.text = tableArrayList[indexPath.row].codeStr
    cell.incidentLoctn.text = tableArrayList[indexPath.row].regionStr

    return cell     //BreakPoint 4
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    AppDelegate.myGlobalVars.gIncName = tableArrayList[indexPath.row].nameStr
    AppDelegate.myGlobalVars.gIncDMA = tableArrayList[indexPath.row].codeStr

    performSegueWithIdentifier("SearchResultsToDetailSegue", sender: nil)
}

func alertView(msg: String) {
    let dialog = UIAlertController(title: "Warning",
                                   message: msg,
                                   preferredStyle: UIAlertControllerStyle.Alert)
    dialog.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
    presentViewController(dialog,
                          animated: false,
                          completion: nil)
}

func downloadIncidents()
{
    var event = AppDelegate.myGlobalVars.gIncName
    var DMA = AppDelegate.myGlobalVars.gIncDMA
    if event == "Enter Event Name" {
        event = ""
    }
    if DMA == "Enter DMA" {
        DMA = ""
    }
    let request = NSMutableURLRequest(URL: NSURL(string: "http://incident-tracker-api-uat.herokuapp.com/mobile/events?name=" + event)!,
                                      cachePolicy: .UseProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.HTTPMethod = "GET"
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        if error != nil {
            self.alertView("Error - " + error!.localizedDescription)
        }
        else {
            do {
                var incidentList: TableData
                if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) as? Array<Dictionary<String, AnyObject>> {
                    for item in json {
                        if let dict = item as? Dictionary<String, AnyObject> {
                            incidentList = TableData()
                            if let nameStr = dict["name"] as? String {
                                incidentList.nameStr = nameStr
                            }
                            if let codeStr = dict["dma"] as? String {
                                incidentList.codeStr = codeStr
                            }
                            if let dateStr = dict["supplyOutageStart"] as? String {
                                let tmpStr = dateStr
                                let index = tmpStr.startIndex.advancedBy(10)
                                incidentList.dateStr = tmpStr.substringToIndex(index)
                            }
                            if let regionStr = dict["region"] as? String {
                                incidentList.regionStr = regionStr
                            }
                            self.tableArrayList.append(incidentList)
                        }
                    }
                    self.spinnerView?.hidden = true
                    self.indicator?.stopAnimating()
                    self.table?.reloadData()     //BreakPoint 3
                }
            }catch let err as NSError
            {
                self.alertView("Error - " + err.localizedDescription)
            }
        }
    })
    task.resume()      //BreakPoint 1
}

运行该类时,它先击中BreakPoint 1,然后击中BreakPoint 2,然后快速进入BreakPoint 3,然后再次到达BreakPoint 2.然后,它会在cellForRowAtIndexPath()中达到断点4之前延迟大约20到30秒,然后数据会加载到UITableView中.此视图随后会快速显示.

可以非常快地从Web服务检索数据,那么为什么在将数据加载到tableView之前会有明显的延迟?是否需要穿线Web服务方法?

解决方案

您正在后台线程中获取服务器响应,因此需要在UI线程上调用reloadData()函数.我怀疑等待时间会有所不同,具体取决于您是否与应用进行交互(实际上会调用UI线程),并且该时间实际上是表实际显示新数据的时间.

简而言之,您需要用

dispatch_async(dispatch_get_main_queue()) {
    // update some UI
}

包裹self.table?.reloadData() //BreakPoint 3

dispatch_async(dispatch_get_main_queue()) {
    // update some UI
}

最终结果将是

Pre Swift 3.0

dispatch_async(dispatch_get_main_queue()) {
    self.table?.reloadData()
}

发布Swift 3.0

DispatchQueue.main.async {
    print("This is run on the main queue, after the previous code in outer block")
}

I'm loading my UITableView from an Api call but although the data is retrieved fairly quickly, there is a significant time delay before it is loaded into the table. The code used is below

import UIKit

class TrackingInfoController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var table : UITableView?
@IBOutlet var indicator : UIActivityIndicatorView?
@IBOutlet var spinnerView : UIView?

var tableArrayList = Array<TableData>()

struct TableData
{
    var dateStr:String = ""
    var nameStr:String = ""
    var codeStr:String = ""
    var regionStr:String = ""

    init(){}
}

override func viewDidLoad() {
    super.viewDidLoad()

    table!.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    spinnerView?.hidden = false
    indicator?.bringSubviewToFront(spinnerView!)
    indicator!.startAnimating()
    downloadIncidents()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

@IBAction func BackToMain() {
    performSegueWithIdentifier("SearchToMainSegue", sender: nil)
}

//#pragma mark - Table view data source

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1     //BreakPoint 2
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return tableArrayList.count;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell

    cell.incidentDate.text = tableArrayList[indexPath.row].dateStr
    cell.incidentText.text = tableArrayList[indexPath.row].nameStr
    cell.incidentCode.text = tableArrayList[indexPath.row].codeStr
    cell.incidentLoctn.text = tableArrayList[indexPath.row].regionStr

    return cell     //BreakPoint 4
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    AppDelegate.myGlobalVars.gIncName = tableArrayList[indexPath.row].nameStr
    AppDelegate.myGlobalVars.gIncDMA = tableArrayList[indexPath.row].codeStr

    performSegueWithIdentifier("SearchResultsToDetailSegue", sender: nil)
}

func alertView(msg: String) {
    let dialog = UIAlertController(title: "Warning",
                                   message: msg,
                                   preferredStyle: UIAlertControllerStyle.Alert)
    dialog.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
    presentViewController(dialog,
                          animated: false,
                          completion: nil)
}

func downloadIncidents()
{
    var event = AppDelegate.myGlobalVars.gIncName
    var DMA = AppDelegate.myGlobalVars.gIncDMA
    if event == "Enter Event Name" {
        event = ""
    }
    if DMA == "Enter DMA" {
        DMA = ""
    }
    let request = NSMutableURLRequest(URL: NSURL(string: "http://incident-tracker-api-uat.herokuapp.com/mobile/events?name=" + event)!,
                                      cachePolicy: .UseProtocolCachePolicy,
                                      timeoutInterval: 10.0)
    request.HTTPMethod = "GET"
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        if error != nil {
            self.alertView("Error - " + error!.localizedDescription)
        }
        else {
            do {
                var incidentList: TableData
                if let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments) as? Array<Dictionary<String, AnyObject>> {
                    for item in json {
                        if let dict = item as? Dictionary<String, AnyObject> {
                            incidentList = TableData()
                            if let nameStr = dict["name"] as? String {
                                incidentList.nameStr = nameStr
                            }
                            if let codeStr = dict["dma"] as? String {
                                incidentList.codeStr = codeStr
                            }
                            if let dateStr = dict["supplyOutageStart"] as? String {
                                let tmpStr = dateStr
                                let index = tmpStr.startIndex.advancedBy(10)
                                incidentList.dateStr = tmpStr.substringToIndex(index)
                            }
                            if let regionStr = dict["region"] as? String {
                                incidentList.regionStr = regionStr
                            }
                            self.tableArrayList.append(incidentList)
                        }
                    }
                    self.spinnerView?.hidden = true
                    self.indicator?.stopAnimating()
                    self.table?.reloadData()     //BreakPoint 3
                }
            }catch let err as NSError
            {
                self.alertView("Error - " + err.localizedDescription)
            }
        }
    })
    task.resume()      //BreakPoint 1
}

When the class is run, it hits BreakPoint 1 first and then hits BreakPoint 2 and then quickly goes to BreakPoint 3, it then goes to BreakPoint 2 once more. Then there is a delay of about 20 to 30 seconds before it hits Breakpoint 4 in cellForRowAtIndexPath() and the data is loaded into the UITableView. The view is displayed quickly afterwards.

The data is retrieved quite quickly from the Web Service so why is there a significant delay before the data is then loaded into the tableView? Is there a need to thread the Web Service method?

解决方案

You are getting server response in a background thread so you need to call the reloadData() function on the UI thread. I am suspecting that the wait time can vary depending on whether you interact with the app, which effectively calls the UI thread, and that's when the table actually displays the new data.

In a nutshell, you need to wrap the self.table?.reloadData() //BreakPoint 3 with

dispatch_async(dispatch_get_main_queue()) {
    // update some UI
}

The final result would be

Pre Swift 3.0

dispatch_async(dispatch_get_main_queue()) {
    self.table?.reloadData()
}

Post Swift 3.0

DispatchQueue.main.async {
    print("This is run on the main queue, after the previous code in outer block")
}

这篇关于获取数据和加载到UITableView之间的时间延迟是多少的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆