Monday 19 December 2011

iOS 5 SDK: how to use Storyboards in iPhone


Storyboarding is one of the most exciting new features about the iOS 5 SDK. Take a look at the wealth of functionality offered by Storyboards in today’s iOS 5 SDK tutorial!
The iOS 5 SDK comes with a lot of new API’s to play with. iCloud is a great new interface for developers to use to make their application create the most seamless user experience possible. ARC presents a very fundamental shift in memory management throughout your applications. But arguably the most disruptive addition to the iOS 5 developer tool belt is Storyboarding. Storyboarding is big. It will change the way you write a majority of your interface code and also presents the potential to effect your development workflow as a whole throughout a team. Is storyboarding the right API for your next app? Should you upgrade your existing apps to use it? Let’s dive into this new API some more and see what it has to offer.

Mile High Overview

Essentially, Storyboards are a new type of container available in Xcode to hold collections of NIB/XIB’s. As a result, you may never need to use just an independent *.XIB file again (don’t panic – they will still behave exactly as they have previously if you need to keep using them for now). Not only will a Storyboard file hold a collection of NIBs, but it will also allow you to visually control how those views will segue between each other. This means the entire flow of your app’s interface can be modeled and visualized through your single storyboard file. Generally, interface flow requires the ability to get instances of controllers you want to flow to, send data to those instances, and then actually display those instances with some type of segue or transition. This is all very simple to do using Storyboarding, and using Storyboards instead of XIB files will let you cut a lot of code out of your projects. But Storyboarding doesn’t stop there. Storyboarding can also enable you to create table view cells and table view controllers with simplicity. Let’s take a look at how UIStoryboarding specifically addresses each of these use cases.

Compatibility Considerations

An important consideration before deciding to use Storyboarding is versioning. A project built with Storyboarding will be compatible with iOS 5 and greater. While you could build an app with Storyboarding and create proper checks to use other iOS 4 or prior friendly XIB’s at certain places, that would be a lot of extra work for little pay off. If you are going to need to support releases prior to iOS 5, you should likely use the standard view controller and XIB method of UI development.

Sample Project Code

There is a sample project to accompany this article. You can grab it over at GitHub.

Scene Creation

All of UIStoryboards abilities are interconnected in one way or another, so deciding on a logical entry point to describe the objects is difficult. We will begin by looking at the new Storyboard layout interface and work forward from there. Below you will see an example of a UIStoryboard editor window within Xcode 4.2:
UIStoryboard Editor View Zoomed Out
Here you can clearly see that I have 6 different view controllers presented throughout the flow of the application. For consistency with the official Apple nomenclature, we will refer to each of the storyboard sections as a “scene”. Some scenes will have *.h and *.m view controller files, and some are completely configured in Interface Builder. In the demo project, I present an initial scene that leads to 5 distinctly different scenes. I only have 3 explicitly defined UIViewController subclasses to cover all 6 scenes. This whole flow of moving scenes on and off screen can be composed from this Storyboard layout view. The picture above shows the zoomed out story board view. Here you can not move specific UIKit elements around on the views, but rather you are meant to organize the high level flow of your scenes. Once you have finished that, you can zoom in and begin to specify the details of each scene.
UIStoryboard Editor View Zoomed In

Table View Controllers Rebooted

View Controllers, especially table view controllers, can now be explicitly defined exclusively through Storyboarding. From now on, if you view controller or table view controller contains only static content you can choose to implement the entire thing through the Storyboard editor. Interface Builder’s inspector panes have been updated with everything you need to define a static table view and design your table view cells. Below you can see a zoomed up image of the options to configure these static tables and cells through Interface Builder.
UIStoryboard Static Table View Configuration
UIStoryboard Static Table View Cell Configuration
Table View’s now can be specified as static. This leads to an incredible savings of time if you have faced programmatically creating a complex table view of static data. Here is a screen shot of my static table view in my sample application. Any developer with extensive table view development experience can identify with how long this would have previously taken, but with Storyboarding it took me all of a few minutes.
Sample Application Static Table View
In order to facilitate this, all of the data source information we are so familiar with providing for table views is now visualized through the object hierarchy view in Interface Builder. This will represent all of your tables sections, cells and so on. Keeping an eye on this will let you understand how the WYSIWYG actions you are performing translate into the more traditional data inputs for table views.
Sample Application Static Table Interface Builder Object Hierarchy View
So, as you can see, there is tons of new stuff here! Many applications have non dynamic table views that have previously been implemented with distinct UITableViewControllers, but now you can do them all visually. Remember less code usually means less bugs. There is a lot more cool stuff to check out here with static table views, but we have a lot more to cover so let’s move on.

Prototype Table View Cells

Of course you can use the classical UITableViewDataSource protocol methods to define a table views content programmatically. This will still likely be required for most of your table views. However, storyboards also offers some help here. Interface Builder now has much greater support for defining custom UITableViewCells visually. When you do this, you layout the UI elements in the cell as you would imagine, and the final step is to provide the table view cell with a reuseIdentifier.
Dynamic Table View Cell Definition
With this done you can get an instance of the table view cell by using the following for your tableView:cellForRowAtIndexPath: data source method:

How to send In-App SMS with text


Officially, iPhone OS 4 is out of NDA and I can’t write a post on this. If you have been reading my blogs, you might already know how to send a in-app email Sending a in-app SMS is very similar to this, but with subtle differences.
Prior to iPhone OS 4, developers have to depend on
[[UIApplication sharedApplication] openURL: @"sms:12345678"];
The problem with this is not just that it closes your app, but there is no way to specify the body content of the SMS. Secondly, you are restricted to send the SMS to only one person. However, with the new MessageUI SMS controller, you can send SMS to multiple people at the same time. You can also pre-populate the SMS body field. Developers of famous apps like Whatsapp Messenger, copy the SMS text content to clipboard and open the SMS app to allow users to paste the content. But with this newly allowed In-App SMS sheet, users can send SMS without quitting the app.
So, Let’s get started.

Step 1:

Import the MessageUI Framework into your project and #import the header file into the “.h” file of your controller where you want to open the In-App SMS sheet.

Step 2:

You might already have a button handler IBAction where you want to send the SMS. If not create a Button on your XIB file and write IBActions for it.

Step 3:

The real code
-(IBAction) sendInAppSMS:(id) sender
{
 MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
 if([MFMessageComposeViewController canSendText])
 {
  controller.body = @"Hello from Mugunth";
  controller.recipients = [NSArray arrayWithObjects:@"12345678", @"87654321", nil];
  controller.messageComposeDelegate = self;
  [self presentModalViewController:controller animated:YES];
 }
}
The most important part here is the line [MFMessageComposeViewController canSendText]. When sending a in-app email, you can choose to ignore this (atleast as of now) because most of the devices would have upgraded to iPhone OS 3 and all those devices would have the ability to send in-app email. However, the same doesn’t apply to SMS. Remember that even if a device is running iPhone OS 4, if it’s an iPod touch, it will never be abel to send SMS within app. In this case, I have used a if condition to send the SMS. Practically speaking, you should enable/disable the button the user taps to send the sms based on this. You can add the code that does this in your viewDidLoad method.
Secondly, you have to set the messageComposeDelegate to self and not delegate. If you set the controller.delegate to self, you will not get the didFinishWithResult callback and the In-App SMS sheet will not close.

Step 4:

Implement Delegate Callbacks. In your header file, implement the callbacks, MFMessageComposeViewControllerDelegate and UINavigationControllerDelegate. If you don’t you will get a warning at the line,
controller.delegate = self;
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
 switch (result) {
  case MessageComposeResultCancelled:
   NSLog(@"Cancelled");
   break;
  case MessageComposeResultFailed:
   UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"MyApp" message:@"Unknown Error"
                 delegate:self cancelButtonTitle:@”OK” otherButtonTitles: nil];
   [alert show];
   [alert release];
   break;
  case MessageComposeResultSent:
 
   break;
  default:
   break;
 }
 
 [self dismissModalViewControllerAnimated:YES];
}
That’s it. Your app should now be able to send SMS using the new Message UI sheet.