1
\$\begingroup\$

My tableView is scrolling very slowly because there is a fetch request done in every cellForIndexPath method. I have verified this using instruments. The result of the fetch request determines the color of the label inside the cell.

Here is a solution I am using inside the custom cell:

func configureWith(myObject: MyObject) {
    titleLabel.text = myObject.text
    DispatchQueue.global(qos: .background).async {
        let color = self.getColor(forGroup: myObject.group)

        DispatchQueue.main.async {
            self.titleLabel.textColor = color
        }
    }
}

Is this a good solution?

Edit: Changing qos to userInitiated seems to work slightly better in that the scrolling is still virtually instant and the labels show the right color much faster.

\$\endgroup\$
1
\$\begingroup\$

This is not a good solution to handle fetch requests inside scrolling cellForIndexPath.

1 Fetch request should be asynchronous, because it may take time
2 Fetch request should be called in table view datasource and not in custom cell, because cell can be reused while scrolling
3 Should apply result of fetch request if cell is visible

Code in class where UITablView datasource is implemented-

func getColor(forGroup: Int, completion: @escaping (color: UIColor) -> Void) {
  //fetch request
  //request processing...
  completion(resultColor)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath) as! CustomCell
  let myObject = //object for indexpath
  cell.configureWith(myObject: myObject)
  self.getColor(forGroup: myObject.group) { (color) in
    DispatchQueue.main.async {
      if let cell = tableView.cellForRow(at: indexPath) {
        //this unwrapping is needed as tableview returns nil if cell is not visible
        cell.colorLable(color)
    }
  }
}

In CustomCell file:

func configureWith(myObject: MyObject) {
  titleLabel.text = myObject.text
}
func colorLable(_ color: UIColor) {
  self.titleLabel.textColor = color
}
\$\endgroup\$
1
\$\begingroup\$

In addition to other answers consider this changes to optimize:

  • cache the result of the fetch request to allow scrolling up/down
  • consider a bulk fetch and cache the result
  • pre fetch of the values
  • add the value to the datasource of label text
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.