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.
You might have to check if you are re-using the cells or not.
You can reuse it as below:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NAIndexPath *) indexPath{
static NSString *cellIdentifier = @"Mycell";
cell = [tableView dequeueCellWithIdentifier:cellIdentifier];
if(cell == nil)
cell = [[MyCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: cellIdentifier];
}
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!
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With