UITableView performance with Realm objects in cellForRowAt indexPath
I have many different category sections in my table view loaded from a named variable allProducts
that contains all my Realm objects (type Results<Product>
).
The correct products are loaded in each section, however, since I entered this piece of code:
switch productViewSegmentedControl!.selectedSegmentIndex {
case 0:
allProductsInSection = allProducts.filter("itemgroup = %@", allProductSections[indexPath.section])
case 1:
allProductsInSection = allProducts.filter("itembrand = %@", allProductSections[indexPath.section])
case 2:
allProductsInSection = allProducts.filter("itemtype = %@", allProductSections[indexPath.section])
default:
allProductsInSection = allProducts.filter("itemgroup = %@", allProductSections[indexPath.section])
}
in my method cellForRowAt indexPath
, the UI lags behind when scrolling through the sections of the tableView where there are many items.
Each cell in tableView contains let product = allProductsInSection![indexPath.row]
. The constant product
contains properties for each element from my model class product
.
What can I do to improve the performance of the user interface?
PS each cell is already being reused:
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell") as? OrderFormViewCell
?? UITableViewCell(style: .subtitle, reuseIdentifier: "ProductCell") as! OrderFormViewCell
source to share
Having the instruction switch
in your method tableView(_:cellForRowAt:)
means that you are forcing Realm to re-filter the products every time the cell is displayed. From the code you shared, it looks like you have a segmented control that controls which products to display. Rather than checking the selection of the sharded control when preparing each cell, you should instead react to your selection change and filter your products into an instance variable that you can use tableView(_:cellForRowAt:)
. This will allow Realm to filter products only when the criteria have changed, not every time the cell is displayed.
Since you need to filter using a different value in each section of your table view, you need to prepare one Results
for each section of your table view. In the method you call when the selection of the segment control changes:
var productsPerSection = []
for section in 0..numberOfSections {
let productsInSection: Results<Product>
switch productViewSegmentedControl!.selectedSegmentIndex {
case 0:
productsInSection = allProducts.filter("itemgroup = %@", allProductSections[section])
case 1:
productsInSection = allProducts.filter("itembrand = %@", allProductSections[section])
case 2:
productsInSection = allProducts.filter("itemtype = %@", allProductSections[section])
default:
productsInSection = allProducts.filter("itemgroup = %@", allProductSections[section])
}
productsPerSection.append(productsInSection)
}
self.productsPerSection = productsPerSection
Then in your method tableView(_:cellForRowAt:)
use self.productsInSection[indexPath.section]
instead of filtering to create allProductsInSection
.
Note: The code is an untested sketch that will hopefully provide a general idea of ββthis approach, but probably won't compile.
source to share