Back in the dark ages when I first started programming for iOS (a whole 1.5 years ago), I spent a lot of time banging my head against the wall to get the spot you were typing in your list (implemented as a UITableView with custom cells containing UITextFields) to stay visible when the keyboard came up. I probably didn't have the most elegant solution, but by the time I shipped it, it worked. And that was saying something.
Then iOS 5 came out and strange things started happening without me changing my code at all. It looked like the built-in stuff was trying to manage the problem for me and I was thrilled. I commented out all my math and scrolling commands, hit build and run...
And it failed. Something was happening, some scrolling was going on... sometimes. But it wasn't always the right scrolling. In fact, it often wasn't the right scrolling. So I had to hack through my old code and try to make it work with whatever was now going on in the background.
I asked about the problem at one of the WWDC labs and got some suggestions. I spent yesterday trying to implement them and getting frustrated all over again before finally reaching what seemed like a solution.
Then I started creating a sample project to write it up as a tutorial... and discovered that the automatic, built-in scrolling for the keyboard now just works. Even in a UISplitViewController! My code was completely superfluous.
Terribly excited, I went back to my real project, commented out the now-much-reduced-but-who-cares scrolling logic, and tested it.
It worked! Right up until I tapped "Next", which triggers code that inserts a new row and programmatically makes that cell's textfield the firstResponder...
And nothing scrolled. The very tip of the cursor blinked weakly at me from behind the keyboard.
So, it seems that if you tap into a textfield, the automatic stuff will be just fine. But if you programmatically make a field becomeFirstResponder, you probably need to do more work.
Luckily, the solution I figured out yesterday works for that and isn't too ugly (and doesn't seem to affect the automatic scrolling when that works).
Here's what you do:
1. Create a UITextField property to keep track of which field you're currently editing in. In your textFieldDidBeginEditing method, set your property to the passed textfield. In your textFieldDidEndEditing method, set your property to nil.
2. In your keyboardDidShow method, put the following logic:
-(void)keyboardDidShow:(NSNotification *)aNotification{
// this is needed to handle scrolling so you can see what you're typing if a textfield is made first responder programmatically
if (self.activeField) {
UITableViewCell *containingCell = [self cellContainingField:activeField]; // you need to implement the cellContainingField method yourself depending on your own cell structure. Be aware that the cell is probably not the direct superview of the field so you will probably want your method to do a recursive upwards search.
if (containingCell){
[self.tableView scrollRectToVisible:containingCell.frame animated:YES]; // you would think you could just pass the frame of the activeField in here, but that didn't work for me. No idea why. ETA: it's because the frame of the active cell has its position referenced to the cell's frame, not the tableview's frame. i.e., my active cell is positioned with its left upper corner at (0,0) in its cell. Telling the tableview to scroll to y position 0 is NOT what you want!
}
}
}
And that's it! It would be too painful to tell you how much code that replaces from my original project, so we'll just leave it at that. :)
***
Note: I haven't gotten a chance to test this on a device yet. It works in the simulator and I have my fingers crossed. Please let me know if you have anything to add.







A number of college professors used to say something along the lines of:
если решение не красивая, она не может быть правдой
They were, of course, talking about math and not computer science. Congratulations on the progress!
Posted by: Drewdle | 28 June 2012 at 08:29 AM
I bet you're really, really good at Lego too.
Posted by: Liz W | 28 June 2012 at 07:02 PM
I totally agree with the professors!
Posted by: DiDi | 28 June 2012 at 07:16 PM
Oooo!......this blog is so much fun. The old mental Russian file cards are being dusted off. I think there is something here about if a solution (?) isn't beautiful it can't be true. Sounds like something my Russian professors would have said. Never took much science or math, but I'm sure your solution is beautiful even if I can't understand it (or remember my Russian).
Posted by: mar mar | 28 June 2012 at 09:01 PM