I made a stupid mistake recently, which cost me more than a few hours of time to figure out. But I learned a couple things: Xcode will let you dig as deep a hole as you like, despite its “assistance”, and no amount of experience is a substitute for taking your time, especially when writing code.
I was implementing a custom view recently, with an embedded UITableView. No problem. At this point, we can all probably stub out the required UITableViewDelegate and UITableViewDataSource methods with our eyes closed. Or can we? What’s wrong with this declaration:
– (CGFloat)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
At first blush, nothing. I think we can all agree that we’d remember that this is a required method to implement when working with tables. At least, we’d all certainly remember we need to implement a method named numberOfRowsinSection.
What is wrong here, however, is the return type. There are a lot of places in various protocols where the return type is a CGFloat. So, why not here? In fact, when I implemented this method, I didn’t cut-and-paste the signature from the docs, or even look at the docs. I just started typing, and despite Xcode’s suggestion, which included the correct return type, I pressed on without really looking at the pop-up.
I implemented the method and moved on.
When I began to test my code, however, things got weird. My view controller worked great! The embedded table view worked exactly as I wanted. The first time. If I left my view controller and tried to return to it a second time, the app would crash. And it was one of those nasty what-just-happened-and-how-the-heck-do-I-debug-this?! crashes.
I really spent a lot of time researching, debugging line by line, re-testing, re-jiggering, you name it!
As almost a last ditch effort, I carefully reviewed the implementations of all my UITableView delegate and data source methods. Sure enough, I found I had implemented the above method with the wrong return value. And when I changed it to correctly return an NSInteger instead of a CGFloat, all was right with the world.
I chalk up this mistake, honestly, to haste. I was in a hurry. I knew what I needed to do. Clearly I didn’t know enough to look twice. 🙂 This all happened on one of my personal projects, but it’s a good lesson and reminder that haste makes waste, even in software development.