A Tale of Two Table Views - my UISearchBar Race Condition that I finally found

September 8, 2010    

OK, so I finally found my race condition, I’d talked about here and here.

So, in my KidChart app, I have a UITableView that has a list of all behaviors that people can pick from:

 

 

and in the search box above, people can start typing to narrow down existing behaviors and then click on one so they don’t have to scroll as much. As soon as the UISearchBar gets focus, it does this:

 

Now that tableview that has the 3 items that contain “o” is a different tableview than the one above. It’s the tableview that belongs to the UISearchBar, as opposed to the one in my view.

Turns out, though that under some circumstances, core data events get triggered. And those events cause the UITableView to get refreshed. Shouldn’t have been the end of the world, except it causes Both UITableView to get refreshed, both the filtered one that belongs to the UISearchBar, and the underlying, currently hidden one, that was there before the UISearchBar got focus. And the mistake I made was that I was reusing the same NSFetchedResultsController behind the scenes for both UITableViews (since I naively expected only one to be updated at a time). Most of the time, it seems one would get completely refreshed before the other refresh started, but sometimes (and more often on the iPhone 4), the calls to cellForRowAtIndexPath would get interleaved, causing unpredictable results, and the occasional crash.

Thank you, automated testing.

(And thank you Mike Uricaru who suggested a way for me to be able to use UIASearchBar.setValue() in the UIAutomation Javascript - without the race condition, it does work, and it’s much faster to run than taping each key by hand - although I still use the keystroke at a time to test that I’ve gotten the filtering behavior correctly).