大型uitableview(1000行)在reloadData()上冻结

时间:2017-07-19 13:59:31

标签: ios swift uitableview

我有一个大约1000行的UITableView。我还有一个每6秒运行一次的计时器从Web服务获取数据。每次我调用reloadData()都会有一个短暂的问题 - 我的应用程序会在短时间内非常明显地冻结。滚动时非常明显。 我尝试仅提取大约400行,然后blip消失。任何提示如何在仍然获取1000行的同时摆脱这个?

#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <cstdio>

#define USER_TYPES_INPUT // comment this line out to use own test stream
#ifdef USER_TYPES_INPUT
auto& my_cin = std::cin;
#else
std::stringstream my_cin{R"(khff&%/32 1)"};
#endif

int main()
{
    std::string line;
    std::cout << "Enter a number of mixed characters: \n";
    std::getline(my_cin, line);
    auto original_size = line.size();
    auto space_count = std::count_if(line.begin(), line.end(), [](auto c){return ::isblank(c); });
    line.erase(std::remove_if(line.begin(), line.end(), [](char c){ return !::isalnum(c); }), line.end());
    std::transform(line.begin(), line.end(), line.begin(), [](auto& c){return ::toupper(c); });
    std::sort(line.begin(), line.end());
    std::cout << original_size - line.size() << " characters were filtered out, out of which "
        << space_count << " whitespace" << (space_count == 1 ? " was" : "s were") << " encountered.\n";
    std::cout << "New sorted string: " << line << '\n';
    return 0;
}

UITableViewDataSource代码:

var items: [Item] = []

Timer.scheduledTimer(withTimeInterval: 6, repeats: true) { [weak self] _ in
   guard let strongSelf = self else { return }

   Alamofire.request(urlString, method: method, parameters: params) { response in
      // parse the response here and save it in array called itemsFromResponse
      OperationQueue.main.addOperation {
         strongSelf.items = itemsFromResponse
         strongSelf.itemsTableView.reloadData()
      }
   }
}

2 个答案:

答案 0 :(得分:1)

问题是由于您正在存储响应中的项目,然后从同一OperationQueue更新表视图,这意味着在更新阵列时阻止了UI线程。如果您不需要对任务进行细粒度控制(例如取消和高级调度,就像您在此不需要那样),则使用操作队列本身并不是调度任务的最佳方式。您应该使用DispatchQueuesee here for more

为了解决您的问题,您应该从后台完成处理程序更新数组,然后更新您的表。

Timer.scheduledTimer(withTimeInterval: 6, repeats: true) { [weak self] _ in
   guard let strongSelf = self else { return }

   Alamofire.request(urlString, method: method, parameters: params) { response in
      // parse the response here and save it in array called itemsFromResponse
      strongSelf.items = itemsFromResponse
      // update the table on the main (UI) thread
      DispatchQueue.main.async {
         strongSelf.itemsTableView.reloadData()
      }
   }
}

您还应该考虑一种更有效的方式来获取新数据,因为每6秒重新加载整个数据集在用户手机上的数据或CPU方面效率不高。

答案 1 :(得分:-1)

问题是你每6秒重新加载一次数据,所以如果数据太大,你每6秒重新加载1000行。我建议您请求数据并比较是否有新数据,因此在这种情况下您需要重新加载数据,或者您只需要刷新一次。例如:

var items: [Item] = []

Timer.scheduledTimer(withTimeInterval: 6, repeats: true) { [weak self] _ in
   guard let strongSelf = self else { return }

   Alamofire.request(urlString, method: method, parameters: params) { response in
      // parse the response here and save it in array called itemsFromResponse
      OperationQueue.main.addOperation {
         if(strongSelf.items != itemsFromResponse){
            strongSelf.items = itemsFromResponse
            strongSelf.itemsTableView.reloadData()
         }             
      }
  }