Being new to iOS environment, I watched different tutorials: the latest
Stanford iOS classes uses
storyboard for almost all demos, reading
big nerd ranch iOS programming book,
Interface Builder (xib files or in their binary form nib file) are much prefer over storyboard, looking at source code in
TODO sample none of those methods are used. Everything is crafted by hand, which I will call in the rest of the blog the
hand-crafted approach. Which one to choose?
First of all, all of them work, it's just a matter of finding which one works best for you. Which can you app are you making? Are you working alone? Are you an addicted to IDE or you'd rather use plain old text editor? Are you more a mouse person or a a do-it-all-with-the-keyboard guy?
I try the different ways with one simple example: I want to build an App that displays a list of item. We want to create a ViewController named
MyViewController which inherits from UITableViewController. All source code could be found
here.
Hand-crafted
Step1: Create Xcode project with empty template
Open Xcode and go to File -> New Project, select the Empty Application template
Step2: Add new file MyViewController
and make it extends UITableViewController
Step2: Link MyViewController to AppDelegate
By adding property at line 4:
@interface MyAppDelegate : UIResponder
@property (strong, nonatomic) UIWindow *window;
@property(strong, nonatomic) MyViewController *viewController;
@end
Step3: Take care of initialisation of AppDelegate
Once the application is loaded, it's the developer's duty to instantiate MyViewController. As per commonly used Delegate pattern, once app is loaded the delegate method
application:didFinishLaunchingWithOptions: is called. Within this method, you should add line 6-7
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customisation after application launch.
self.window.backgroundColor = [UIColor whiteColor];
self.viewController = [[MyViewController alloc] initWithStyle:UITableViewStylePlain];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Step4: Implement your model in MyViewController
For the example we feed an array of fake data in it setter method.
@implementation MyViewController
NSArray *_items;
- (NSArray *)items{
_items = [[NSArray alloc] initWithObjects:@"Item No. 1", @"Item No. 2", @"Item No. 3", @"Item No. 4", @"Item No. 5", @"Item No. 6", nil];
return _items;
}
Step5: Display your model in MyViewController
To display the content od a cell you need to conform to protocol
UITableViewDataSource, tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: are the two methods responsible for the display of a cell.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell... setting the text of our cell's label
cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
return cell;
}
That's it you're all done, run the app!
Interface Builder
Xib, nib depending if it's the next generation or not. Actually xib file is the xml source file which describes your view. Nib being the compiled version.
Step1: Create Xcode project with Single App template
Open Xcode and go to File -> New Project, select the Single View Application template
In the next step make sure you have the option
Use Storyboard unchecked.
No need to add code in AppDelegate's
application:didFinishLaunchingWithOptions:, the code has been added for you. See line 5-6.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[AGViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Step2: Implement your view with xib view
1. drag and drop Table view from object library in utilities bar.
2. create an outlet, drag and drop (with control key down) up to MyViewController interface.
3. link data source to file owner: right click on TableView all the way to file's owner in document view.
Step3: Implement your model in MyViewController
Same code than Hand-crafted approach step4.
Step4: Display your model in MyViewController
Same code than Hand-crafted approach step5.
Run the app an you will have the same result. As you can see there is less code to write, but the approach involved more mouse actions. One piece of code that was generated for you but which is important to understand is in step1, the call to
initWithNibName:bundle:; One interesting stuff with Interface Builder is that you can mix handcrafted and interface builder. The strength of a WYSIWIG widget based tool like Interface Builder is to build complex customized view. If you have to build a Custom Cell for you TableView, you could use Interface Builder and then load the archive and associate it with the relevant object.
Storyboard
Introduced in iOS5, Storyboard carries on the WYSIWYG approach launched by Xib. Sometime seeing as a replacement of nib, it brings UI definition in one simple file rather than several xib files, also deal with transition between screen.
Step1: Create Xcode project with Single App template
Same as for Interface builder, but this time make sure Use Story board option is checked.
Step2: Make connection from storyboard to your code
1. Go to .storyboard file, select the UIViewController graphic
2. On the utilities tab, in the identity inspector, change the class field to match MyViewController
3. create an outlet: holding the ctrl key with a drag from your view in storyboard to MyViewController.h file. Once you drop you will be prompted to enter a name, and click connect. this is the magic part of Apple WYSIWYG editor and how the link to source code. All newbies get surprised here.
Step3: Connect the datasource with outlet
Remember for hand-crafted we had to implement 2 protocols data source and delegate one. Same thin here, right click on TableViewController in the storyboard. From the outlet section, drag and drop to My Table view controller. Do it for data source and delegate.
Step4: Implement your model in MyViewController
Same code than Hand-crafted approach step4.
Step5: Display your model in MyViewController
Same code than Hand-crafted approach step5.
Run the app an you will have the same result. Here again, there is less code to write, but the approach involved more mouse actions. Besides, I thing the strength of storyboard comes when you have an application with several views and transitions using
segues.
As a conclusion, we've seen the different approaches, I think to start with it's easier with the hand-crafted approach as you get to understand frequently used patterns in iOS like the Delegate pattern. But then I might be biased as I have a developer background. I like the idea Xcode storyboard/xib approach , I think it's nice to prototype or to experiment (like a preview you see it right away) but at the end of the day I find source code easier to maintain. It's all written in plain code. But you know what, storyboard/xib file are be all written in plain XML too ;) Right click and open then as source code.
Do you prefer to write XML or Objective-C?