i’m so full of ideas

Archive for the 'objective-c' category

iPhone: using UITextField with the virtual keyboard

March 5, 2009 12:27 pm
keyboardscroll main window

keyboardscroll main window

UPDATE: this blog post is now obsolete. I wrote it before I knew enough about the subject to be pontificating on it. Please read my newer blog post on this subject instead.

Now I feel bad. In the last two days, about ten people found their way to my blog by using search terms that suggest they are having as much trouble with the iPhone keyboard as I did. I spent a whole day figuring it out. Then I wrote a blog entry where I just bitched about it, rather than presenting an actual solution. Sorry for wasting your time, folks. Today I give you an example Xcode project that demonstrates how to code for the iPhone’s virtual keyboard, as an act of atonement.

I got most of this stuff from UICatalog, Apple’s sample project that demonstrates the use of most UIKit controls. Some of it didn’t work very well for me, so I modified it a bit. For example, UICatalog not only scrolls the view up to make room for the keyboard, it also shortens the view at the top by the appropriate number of pixels. That caused unpleasant side effects for me, so I did away with that part.

UICatalog was difficult for me to follow, because they’re trying to demonstrate so much stuff at once. It took me awhile to figure out what parts were relevant to my situation. My keyboardscroll project is quite small, so it should be easier for you.

As mentioned previously, I don’t like Interface Builder. Therefore, this project is “nibless,” completely free of XIBs and NIBs. That shiz be stanky, yo. So you could also consider this project to be an example of how to lay out your views entirely in code, if that’s something that interests you.

The keyboardscroll app presents an interface that looks similar to the iPhone’s SMS app. The top part of the window is taken up by a UITextView full of scrolling text. There is a UITextField at the bottom of the window, where the user can type in new text. When the user presses the “Send” button, the text typed is added to the UITextView at the top.

It is impossible to do iPhone programming without making use of magic pixel counts. To keep the damage to a minimum, I put all the magic numbers at the top of ViewController.m and copiously documented them. Most mysterious of all is how many pixels to scroll up when the keyboard appears. Every time I do this, I need to use a different pixel count. It seems like Apple could give us some help here. Perhaps a method to call that would tell you how far up your view has to go to avoid the keyboard.

iphone newbie: view coords, UITextField

March 3, 2009 7:49 am

View coordinates for iPhone

I count three people in my access logs who got here by searching for iPhone programming material, two who are trying to create nibless apps. Rock on, fellow Interface Builder haterz!

iPhone programming is typically very similar to Mac programming. One big change I’ve noticed is that they’ve moved the origin for view coordinates. For NSView on the Mac, the origin point is at the lower left corner, Y coords get bigger as you move up the window. That always seemed deeply, profoundly wrong to me. I guess I’m not the only one who feels that way, because on the iPhone, the origin point is now in the upper left corner, with Y coords getting bigger as you move down the view.

To make matters worse on the Mac, it’s possible to have an NSView with “flipped” coords. In that mode, the origin point is at the top left, as god intended. Some of the stock views are like this, I think NSTableView is one of them. Those views will go crazy if you try to set them back to the “normal” Mac way, displaying their contents incorrectly. What a mess. Looks like iPhone/UIView doesn’t have the “flipped” concept, so everything’s cool again.

View coordinates for Mac

Well, except for other annoyances. Today’s culprit: UITextField. This is the standard one-line text input control for the user to type into, analogous to the Mac’s NSTextField. Way, WAY more complicated than it should be. Every single thing that happens to it in its lifetime, you have to write custom code for.

Creating a UITextField and adding it to a parent view is a trial-and-error affair, sprinkled with magic pixel counts like 30.0 and 4.0 and so on. It’s not just me, that’s the way they do things in Apple’s UICatalog sample app, which shows you how to create most control types. This is bad. What if the dimensions of the control change in the next iPhone software update?

When the user touches the control, the onscreen keyboard pops up. Surprise! It will almost certainly cover the UITextField the user is typing into, so they can’t see what they’re doing. The next step is that you have to write code to scroll your view up to get out of the keyboard’s way when it appears, then scroll the view back down when the keyboard disappears. Why isn’t the iPhone OS doing this for me? Madness!

Now you must add code to your view controller’s viewWillAppear: method, to catch notifications for when the keyboard appears and disappears. Then add more code to viewWillDisappear: to disable those notifications. Then write a method that gets called when the keyboard appears or disappears, to scroll your view up or down by a magic number of pixels. UICatalog hard-codes the value 150.0, which is I suppose the height of the onscreen keyboard. That wasn’t quite right for me, I discovered I needed it to be 166.0. I’m sure that will be the right value to use always and forevermore, right Apple? Sheesh.

Finally, the keyboard won’t ever go away unless you write more code to dismiss it. You must make your view controller the text control’s delegate and write a textFieldShouldReturn: method so you can do something with the Enter key and tell the keyboard to go away. Six new methods later, your quest is at an end. Until the next time you need a UITextField.

nibless

February 23, 2009 7:59 pm

Update: The linked blog post in this article that explains how to create a nibless Xcode project is now dead. Go read this post instead.

This might sound heretical, but here goes: I don’t like Interface Builder.

I used the 2.x versions to build this. I got along with it acceptably well at the time, I guess, although it was never my favorite program. Then Apple completely rewrote it from the ground up for 3.0, whenceforth it didst suck, yea verily.

My complaint is a simple one: Interface Builder is 87 billion times more complex than it should be. Dozens of windows, hundreds of tabs, thousands of buttons, sliders, text input fields, check boxes, outlets, hinges, beads, knobs, joints, pipes, and zippers. Every time I start it up, I dread the ordeal I know I’m in for. It takes me half an hour to find the one check box I need in a sea of extraneous crud. Once I get a view or window set up appropriately, the steps I went through to get there are not easily documented or remembered.

I know that laying out user interfaces and wiring up controls is a big job. I know that somebody must need all that crud I never use, or it wouldn’t be there. But couldn’t Apple use its legendary user interface skills to de-emphasize the infrequently-used parts? I’m dyin’ here.

If you’re writing a Mac/Cocoa app, I guess you’re stuck with it. You’ve probably got at least a few fairly complicated windows to manage, along with dozens of menu items. But if you’re writing an iPhone/UIKit app, the value proposition changes. iPhone apps tend to have only a handful of user interface objects and connections. In this scenario, Interface Builder’s weaknesses outweigh its strengths.

It’s easy to assume that it’s impossible to build an iPhone or Mac app without Interface Builder. As a matter of fact, I once spent several months figuring out how to build Cocoa apps without NIBs, because I was writing a cross-platform GUI framework, so obviously they had to go. It wasn’t easy, because it’s not done very often, but I succeeded. And the first version of the iPhone SDK didn’t even give you the opportunity to use Interface Builder, you were forced to create your user interface in code.

Now we reach the part of the blog entry where I should tell you how to make an iPhone app without NIBs. Alas, this gentleman has already done a far better job of it than I would have. So you can instead read what he wrote, secure in the knowledge that someone else produced a solution, while I produced a bunch of hot air and whining. You’re welcome.

I’m now working on the user interface for my first iPhone app. I have several views set up, all completely NIB-free. It’s far preferable to create a user interface element in 10 lines of code, rather than making yet another soul-destroying 20-minute slog through Interface Builder. I suppose it’s possible that I’ll run into some situation that forces me to reconsider, but at this point, I’m willing to go far, FAR out of my way to avoid having to invite that sad piece of software back into my life, thank you very much.