iosswiftuitableviewearlgrey

UITableView.reload leaves old cells in TableView but hidden


I have a UITableView used to show search results. As I type, I’m calling Tableview.reloadData(). Visually, everything works. As I begin typing, I show up to 5 matches and as I go below that, the list will show fewer items correctly. Here are the how the cells are created and number of rows reported.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "placeCell") as! PlaceCell
    if shouldShowSearchResults {
        let place = filteredPlaces[indexPath.row]
        cell.dataSource = place
    } else {
        let place = allPlaces[indexPath.row]
        cell.dataSource = place
    }
    cell.delegate = self
    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if shouldShowSearchResults {
        vlog?.debug("Number of FILTERED rows in PlacesTableView: \(filteredPlaces.count)")
        return filteredPlaces.count
    } else {
        vlog?.debug("Number of unfiltered rows in PlacesTableView: \(allPlaces.count)")
        return allPlaces.count
    }
}

Since the PlaceCell is a custom class, here are some details of it:

// I've omitted labels, etc.
class PlaceCell: UITableViewCell {

    var dataSource : PlaceView? {
        didSet {
            if let ds = dataSource {
                self.isAccessibilityElement = true
                self.accessibilityLabel = ds.getAccessibilityLabel()

            } else {
                self.isAccessibilityElement = true
                self.accessibilityLabel = nil
            }
        }
    }
    weak var delegate : PlaceCellDelegate? = nil

    override func prepareForReuse() {
        self.isAccessibilityElement = false
        self.accessibilityLabel = nil
        super.prepareForReuse()
    }
}

I began noticing a problem when UI Tests using Google's Earl Grey began failing due to multiple cells with the same Accessibility Label. Visually, I didn't understand why this was failing since there was only one cell visible that matched.

Upon inspect the views using Reveal, it seems that, as the count of cells drops below what was the maximum of 5, the old cells are still in the TableView, but hidden. So there is a hidden cell that used to be displaying the same data as is displayed by a different cell.

Any idea why this would be happening? This has worked for a number of months and I'm not sure what's changed.


Solution

  • It is always perilous when you traverse the view hierarchy; things can change, and perhaps that is what has happened here.

    Regardless, you can make your test more robust by only selecting the visible item with the required label by using grey_sufficientlyVisible

    Something like:

    grey_allOf(grey_accessibilityLabel("Whole Foods Market, East Mayo Boulevard, Phoenix"), grey_sufficientlyVisible(), nil)