Laggy TableView scrolling

In my tableview I have a few custom cells. When I scroll in the tableview it lags in the same spot but only for the first time the app is open. if I go back to the root view then open the tableview again it doesn't seem to lag. I've traced the lag to one cell. In that cell I have an embedded collection view and each of those cells has image view with is showing a MKMapSnapshot and also a few labels etc. If run with 0 collectionView cells (numberOfCellsInSection) the tableview scrolls smoothly but lags when I have 1 or more CollectionViewCell cells.

I initially loaded the image in the collectionView cell class in layoutSubviews which worked but I then learned that this is called numerous times so code like that shouldn't be there. if I put it in awakeFromNib the Branch struct doesn't seem to have been passed to the cell as yet (from cellForRowAt) so it doesn't work there. I then moved setting the image in cellForItemAt but I'm still not sure if it is correct there.

// Table View cellForRowAt
        case .branchesCell:

            let cell = tableView.dequeueReusableCell(withIdentifier: "branchesCell", for: indexPath) as! BranchesCell

            cell.branches = restaurant?.branches // This is the info the embedded collectionView cell should display. Text for labels and coordinates for the MKMapSnapshot.

            return cell
// TableView Cell Class

class BranchesCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet var collectionView: UICollectionView!

    var branches: [Branch]?
    var restaurantName = String()

    override func awakeFromNib() {
        super.awakeFromNib()

        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.backgroundColor = .clear
        collectionView.delaysContentTouches = false
    }


    // MARK: UICollectionView

    func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 }


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        if let branches = branches {
            return branches.count
        } else {  return 0 }

    }

    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! NestledBranchCell

        cell.layer.masksToBounds = false
        cell.backgroundColor = .clear

        let imageView = cell.viewWithTag(1) as! UIImageView

        if let branches = branches {
            cell.branch = branches[indexPath.row]
            cell.restaurantName = restaurantName

// Tried to run this in a different thread to see if it would make a difference.
            DispatchQueue.main.async() { [self] in

                let size = CGSize(width: 314, height: 195)
// Set the image here
                getMapImage(branch: branches[indexPath.row], size: size) { mapImage in

                    imageView.image = mapImage

                }

            }

        }

        return cell
    }

    func getMapImage(branch: Branch, size: CGSize, completion: @escaping (UIImage?) -> ()) {

        var mapImage = UIImage()
        let mapSnapshotOptions = MKMapSnapshotter.Options()

        let location = branch.coordinates.coordinate 
        let region = MKCoordinateRegion(center: location, latitudinalMeters: 300, longitudinalMeters: 300)

        mapSnapshotOptions.region = region
        mapSnapshotOptions.scale = UIScreen.main.scale
        mapSnapshotOptions.size = size
        mapSnapshotOptions.showsBuildings = true
        mapSnapshotOptions.pointOfInterestFilter = .none 

        let snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)

        snapShotter.start { snapshot, error in

            let image = snapshot?.image
            mapImage = image!
            completion(mapImage)

        }

    }


}
// Tried to run this in a different thread to see if it would make a difference.
            DispatchQueue.main.async() { [self] in

You put it in the main thread.

Dispatch to another thread:

see pattern here :

  • h t t p s : / / medium.com/capital-one-tech/smooth-scrolling-in-uitableview-and-uicollectionview-a012045d77f
  • h t t p s : / / w w w.raywenderlich.com/7341-uicollectionview-tutorial-prefetching-apis

You could try to use async/await pattern.

I'm facing the same problem, a lag while scrolling table view. I have a tableview-cell in which I've embedded a vertical collection view. I'm also downloading and downsampling the images in the background thread still there is a lag in scrolling. After going through my code I figured out that the collection view cells are not being dequeued as the table view scrolls instead they are kept in memory until the parent tableView-cell is dequeued. I'm looking for ways to improve my code. It would be a great help if someone can point me in the right direction.

Laggy TableView scrolling
 
 
Q