I don't use Interface Builder
Aug 27, 2011
I don't use Interface Builder (IB). Not anymore.
Somewhere between going through the iPhone to iPad display transition, supporting both portrait and landscape orientation and building screens that are dynamic and parts of it animated, I discovered that life without IB is much sweeter.
Why IB?
IB lets you lay out your user interface visually, with inspectors to tweak the controls' properties. If you work with a designer who is not into programming, it is supposed to let you send the XIBs/NIBs to them and who can tweak it directly without requiring additional work from the developer.
If you have custom built components or do even a little bit of layout in code, your designer wouldn't be able to see how the UI looks like in IB. Also, tweaks could mean animate this button for 0.1 seconds longer which requires changes in the code to see the result.
UI Reuse
You need to keep 2 set of NIBs, 1 for iPhone and 1 for iPad. Controls may need to be laid out differently in different screens, or you might have more functionality when running on the iPad due to the additional screen real estate available.
But often, there is UI that is re-usable across the two screen sizes. Creating your view programmatically makes it much easier to share them. For example, you can detect or pass in the actual screen size.
When you have your views written in code, you can decompose them into functions, methods, classes. Much better than in IB which pretty much can't be reused.
Portrait and Landscape Orientation
Let's face it: the layout system in IB is quite primitive. It lacks the layout managers provided in systems such as Java and Smalltalk. If you use IB, you often do up the portrait mode screen in NIBs and then run code to adjust them when changing to landscape orientation. This mixing of IB and code makes things more confusing and hard to architect.
Fine. So How Do We Do It in Code Instead?
For each screen, I have a controller class and view class pair. Here's the controller class:
@interface MyViewController : UIViewController
@property (nonatomic,retain) UIView* mainView;
@end
@implementation MyViewController
@synthesize mainView;
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:
[UIScreen mainScreen].bounds] autorelease];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
self.view.backgroundColor = [UIColor whiteColor];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.mainView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
//self.mainView.delegate = self; //good to have
[self.view addSubview:self.mainView];
/* TODO: controller is displayed for the first time, do things like
load data, etc */
}
- (void)viewDidUnload {
[uper viewDidUnload];
self.mainView = nil;
}
- (void)dealloc {
/* Call -viewDidUnload here so all releasing of view resources is
only done at 1 place. */
[self viewDidUnload];
//TODO: Release other owned ivars here
[super dealloc];
}
- (MainView*)mainView {
if (!mainView) {
/* We use [UIScreen mainScreen].bounds instead of
self.view.bounds so we don't create self.view as a
side-effect. It's messy because creating self.view will
trigger creation of self.mainView itself */
self.mainView = [[[MyView alloc] initWithFrame:
CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width,
[UIScreen mainScreen].bounds.size.height)] autorelease];
}
return mainView;
}
@end
And here's the corresponding view class:
@interface MyView: UIView
@end
@implementation MyView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
//TODO: assemble your subview and add them to self.view
}
return self;
}
@end
I often build a UIViewController and UIView subclass containing common code which serves as the base class for most view controllers and views in an application.
.
Previous
Aug 01, 2011
Comments about Straits Times iOS appJul 11, 2011
Trying out Safari againJul 11, 2011
Migrated from Posterous to BlogofileMay 17, 2011
In-app Purchase Patent and What iOS developers Should Know About ItJan 12, 2011
Using ctags with MacVim for Objective C on OS XJul 06, 2010
Glass Buttons in iPhone Apps Without Using Image FilesJun 03, 2010
My SimplyTweet Punch CardJun 01, 2010
How to Report a Bug in a Software to the DeveloperMay 18, 2010
You can copy and paste from/to the iPhone simulatorApr 12, 2010
Can't Download Xcode Because Session Keeps ExpiringJan 24, 2010
Disable Callouts for Links with Custom Schemes in UIWebViewJan 15, 2010
Script to Remove Core Data's SQLite Database File During Development CyclesDec 17, 2009
Registered http://settingsapp.com/ a Few Days AgoDec 06, 2009
Automating Internet Sharing on OS X Snow LeopardSep 07, 2009
Speeding up iTunes-iPhone SynchronizationSep 03, 2009
The Wonderful Review ProcessAug 31, 2009
The Power of 48 MinutesAug 05, 2009
Book about Search User interfaces, full text available free onlineAug 04, 2009
Detailed, well-written, informative iPhone app reviews by Stephen IngrahamJul 22, 2009
CEO Letter to Zappos employees over the Amazon acquisitionJul 20, 2009
Interesting blog by startup letting customers make their own newspapers.Jul 19, 2009
SimplyTweet 2.0, iPhone Twitter App with PushJul 18, 2009
A Color Picker for Developers on the MacMay 26, 2009
How to act when you are 25 and Over (Tomato Nation)May 18, 2009
The best introduction to Git which I have read so far - The Git ParableMay 14, 2009
Preparation for SimplyTweet to handle Twitter's new milestone of 2^16 status IDsMay 08, 2009
How to be a good developer