Thursday, October 29, 2009

UITableView cells are not exactly treated like regular views

I was having a problem that in some cases the selection rect was not matching up with the actual cell bounds in a list with variable height custom cells. The selection rect height was simply wrong in seemingly random ways. But I figured it out and it is because the table is doing some things under the covers.

I had things set up so that the custom cell constructor would add all the subviews it needed and where possible set the positions and sizes. Generally the bottom edge of the cell would be defined the a multiline UILabel that could hold a varying amount of text. So in tableView:cellForRowAtIndexPath I would allocate the cell (when needed) and then call a method on the cell that would populate its data with a passed in object. I also defined layoutSubviews that could make needed adjustments based on the data and also set the height of the multiline UILabel. I also provided a class level method that would return the height of the cell for given text so that I could set the same height for the layout and for tableView:heightForRowAtIndexPath.

It turns out that is the wrong thing to do with table cells. It appears that when the cell in returned to the table, it takes a height right then and saves it aside for the the selection rectangle. layoutSubviews isn't called until later so the heights can mismatch sometimes.

The solution was to call the layoutSubviews code (and not have layoutSubview defined) after I populated the cell but before it is returned to the tableView.

I can understand why it is this way, but I think it should be made explicitly clear that the cell you return for tableView:cellForRowAtIndexPath must match the height you returned earlier.

Thursday, October 1, 2009

Beware simulator caches

I just burnt too much time in a "how the fuck is it doing that?!?" situation.

I was trying to check (on the simulator) a failure case in an iPhone app where it makes an HTTP request for an image but it fails. Easy to test, just turn off Airport, unplug the ethernet, and I am all good.

Amazingly, though, the request succeeded. WTF. Oops, I forgot to get rid of my own cache. And rather than just delete the file, lets just make sure and reset the simulator to make sure everything is gone. That will do it.

Run the test and the image is retrieved. Double WTF.

After more fiddling around and increasing magnitudes of WTFs, while looking in /Users/me/Library/Caches to see if there was a simulator cache a co-worker I asked for another set of eyes noticed that there was a com.. cache. Deleted it and the request finally failed.

Kind of a bug no? Certainly the behavior is markedly different from the device and at the very least it should be deleted upon resetting the simulator or deleting the app from the simulator.