Current Setup
I have a custom cell, loaded from a xib, where most of its space is covered by UITextview. Also that cell may have a few textviews. And there are few more elements (one UIView + 2 UILabels) inside of this cell.
The Problem
I tried removing all those views and lag stays even if I have only one textview. Also, the lag is happening only for the first time. Later on, when I scroll down, and run into another cell with a textview in it, the lag doesn't happen at all.
Additional Info
The thing with this custom cell is that a textview is added to a UIStackView
. At the beginning, a stackview is empty, because I don't know (at development time) how many textviews may/should be there.
I am aware that this is another thing that might affect on performance, but I have solved it ( I guess as best as it could) by checking how many textviews are already found in stackview's arrangedSubviews
array when dequeuing a cell, and based on that info, I just add or hide views appropriately (rather than to destroying, and re-creating a required number of textviews each time).
I have tried using Instruments, but I didn't noticed that any of my classes take up CPU time, but rather some UIKit
method calls that are called by the framework internally are the cause of this... If needed, I can post a screenshot, but I guess this is not relevant because those seem to be the usual system & framework calls. Plus I am testing on iPad 2 :D so maybe that is a thing (I have to optimize an app for slow devices).
Still, I guess I can optimize this somehow?
The MyCell class is rather simple (pseudo code):
class MyCell:UITableViewCell{
func configure(data:SomeData){
self.addOrHideViewsIfNeeded()
}
private func addOrHideViewsIfNeeded(){
//here, I check if stackview.arrangedSubviews has, and how many subviews are there, and
//add / hide them appropriately, means if I have to add them, I load them from the nib, otherwise, I reuse views from by adding them/removing them from a pool.
}
}
Also the lag is more noticealbe in Debug version in compare to Release version, which make sense, but it is still noticeable.
Ok this is a sketch of my idea to do the preloading in an invisible from user perspective tableview row zero.
class MyCell : UITableViewCell {
static var initiallyPreloaded : Bool = false
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
if !MyCell.initiallyPreloaded {
//Do the initial preloading setup by adding UITextView to self.contentView
MyCell.initiallyPreloaded = true
} else {
//Setup the regular cell content otherwise
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
class ViewController: UIViewController , UITableViewDelegate {
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell{
var cell: MyCell? = tableView.dequeueReusableCell(withIdentifier: "myCellIdentifier") as! MyCell?
if cell == nil {
cell = MyCell(style: .default, reuseIdentifier: "myCellIdentifier")
}
if indexPath.row == 0 {
//Display the initial cell in unnoticeable to user way (start with hidden/alpha zero)
//For this zero-th row the initial preloading should happen
}
return cell!
}
}