I’ve an app utilizing UITableView
the place an array knowledge is first fetched from a 3rd occasion api, then every merchandise of the array knowledge wants some native processing which takes a little bit of time, then that processed knowledge must be inserted into the UITableView
. How lengthy every merchandise of the array wants for processing will fluctuate loads. As soon as the desk reaches the underside, extra knowledge is fetched and the identical course of happens once more.
The explanation I’m doing the processing on every merchandise of the array knowledge and including it one after the other as an alternative of processing all of it directly and inserting it suddenly is as a result of this permits me to indicate at the very least a few of the knowledge to the consumer instantly as an alternative of the consumer ready for a number of seconds earlier than all the info seems.
I’ve simulated my state of affairs with the next easy code with none API:
import UIKit
import SnapKit
struct Report : Codable {
var title : String?
var element : String?
func titleAttributedText() -> NSAttributedString? {
guard let t = title else {
return nil
}
return NSAttributedString(string: t, attributes: [.foregroundColor : UIColor.white, .font : UIFont.systemFont(ofSize: 20, weight: .bold)])
}
func detailAttributedText() -> NSAttributedString? {
guard let d = element else {
return nil
}
return NSAttributedString(string: d, attributes: [.foregroundColor : UIColor.darkGray, .font : UIFont.systemFont(ofSize: 14, weight: .regular)])
}
}
class ViewController: UIViewController, UITableViewDataSource {
var tableView = UITableView()
var information = [Record]()
override func viewDidLoad() {
tremendous.viewDidLoad()
tableView.dataSource = self
view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
fetchRecords()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection part: Int) -> Int {
return information.depend
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let reuseIdentifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier) ?? UITableViewCell(model: .subtitle, reuseIdentifier: reuseIdentifier)
let file = information[indexPath.row]
cell.textLabel?.numberOfLines = 0
cell.detailTextLabel?.numberOfLines = 0
cell.textLabel?.attributedText = file.titleAttributedText()
cell.detailTextLabel?.attributedText = file.detailAttributedText()
if indexPath.row > information.depend - 5 && !fetching {
fetchRecords()
}
return cell
}
var fetching = false
let group = DispatchGroup()
let queue = DispatchQueue(label: "delayer", attributes: .concurrent)
func fetchRecords(){
fetching = true
print("fetchRecords")
DispatchQueue.international().async {
for _ in 0...30 {
let timeout: TimeInterval = Double(arc4random_uniform(10)) / 100 // 0 to 0.1 seconds delay
self.group.enter()
self.queue.asyncAfter(deadline: .now() + timeout) {
self.group.depart()
}
_ = self.group.wait(timeout: .distantFuture)
DispatchQueue.most important.async {
self.tableView.performBatchUpdates {
self.information.append(Report(title: "New knowledge (self.information.depend + 1)", element: "Delay: (timeout)"))
self.tableView.insertRows(at: [IndexPath(row: self.records.count-1, section: 0)], with: .automated)
}
}
}
self.fetching = false
}
}
}
My drawback is that when the self.tableView.performBatchUpdates
is going on, the scrolling turns into uneven. If you scroll in the direction of the top of the listing and new knowledge is being inserted, the scrolling is uneven and body fee drops. The above code is ready to display it. In my actual app, it is loads worse.
This is a video recording:
I’ve used Devices Time Profiler
and I see the next:
As you possibly can see, the _performBatchUpdates
is taking on numerous time.
I’m not positive find out how to repair it. Any strategies?