iOS 5: Creating a custom side TabBar using Storyboards and Custom Segues

Recently I have seen people use tab bars that, when in landscape mode, run down the side of the iPad screen. I really like this as it takes up less screen space in general, but also that some of them are smaller in width than Apples own UITabBar, which at 59px I feel is larger than necessary. So in this tutorial I am going to show you how to create your own custom TabBar controller for managing multiple tabs. The entire source for this article can be downloaded from CustomTabBarExample. In response to this stack overflow question here is the DemoTabBar4.0. You can see the full video of this tutorial on YouTube.

Setting up the project.

First download the sample images from here. I have created both retina and non-retina make sure you only use the non-retina versions in interface builder. Opening up a new Xcode project and name the project CustomTabBarExample, unzip the example images and drag them into your project and with, Copying items into destination folder” selected hit finish.

Since we are creating a tab bar that will run down the side of the iPad in landscape mode set the supported device orientations to only support left and right landscape. This completes the setup of our blank project.

Building our CustomTabBarController

Select the Media Library, and drag out the background image for the CustomTabBar, placing it in the far left of the CustomTabBarController.

Notice that by adding image elements from the media library Xcode helpfully puts them inside a UIImageView for us. Add a UIView that covers the tab bar background and set its background colour to transparent. Add 3 buttons to this UIView. Each button has two images one dark grey and the other coloured (cyan or magenta). Set the darker of the two icons as the image for the button’s default state and the coloured image with the suffix _highlighted (this should really have been selected) for the selected state. Create an IBOutlet in the CustomTabBarViewController for the buttons UIView and hook it up so you can access them in code.

Note: These buttons could be added directly to the background UIImageView however, adding them to a UIView controller enables you to iterate through the buttons which as you will see later can be very useful.

Add a UIView that covers the remaining area of the CustomTabBarViewController, this will act as a placeholder for the content of the child views when switching tabs.

Create an IBOutlet in your CustomTabBarViewController class and to hook up the placeholder to it, be sure to synthesise this in the main.

Switching Tabs

Add a new UIViewController to your UIStoryboard and set its Size in the Attributes Inspector to be Freeform and uncheck resize from nib.

Select the UIView contained in the new UIViewController and in the size inspector set its dimensions to the same as those of the place holder (in this case they are 938,748). Copy this UIViewController two more times so we have one for each tab and set the background colour of each of the views housed in these UIViewControllers differently so you can see them change when you tap a tab.

In the CustomTabBarController implement the perform segue method like so.

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"HomeSegue"]
       || [segue.identifier isEqualToString:@"HeartSegue"]
       || [segue.identifier isEqualToString:@"CogSegue"]){

        for (int i=0; i<[self.buttons.subviews count];i++) {
            UIButton *button = (UIButton *)[self.buttons.subviews objectAtIndex:i];
            [button setSelected:NO];
        }

        UIButton *button = (UIButton *)sender;
        [button setSelected:YES];
    }
}

Here you can see why adding the buttons to a UIView is useful, rather than having to comparing individual buttons we just need to loop through the buttons on the view to deselect the current selected item. Then select the button tapped to reflect the tab that is being shown.

Creating the Custom segue

Connect the Home button up to its UIViewController by right clicking on the button and dragging to the UIViewController, in the resulting popup choose custom as the transition style.

We now have to define what this custom transition will look like. We do this by creating a subclass of UIStoryboardSegue and overriding the perform method like so,

 
- (void) perform {
 
    CustomTabBarViewController *src = (CustomTabBarViewController *)self.sourceViewController;
    UIViewController *dst = (UIViewController *) self.destinationViewController;
 
    for(UIView *view in src.placeholderView.subviews){
        [view removeFromSuperview];
    }
 
    src.currentViewController = dst;
    [src.placeholderView addSubview:dst.view];
}

This implementation will take the source of the segue, in our case the CustomTabViewController and remove all of the subviews of the placeholder view we setup before finally adding the subview of the destination controller to the placeholder view. You will also note here that I have added another property to the CustomTabViewController called src.currentViewController, this keeps a handle to the UIViewController that owns the view being displayed. Now you have to set each of the Segues to be of this type to ensure this transition is indeed what is being used and create identifiers for each Segue. If you are using my code from above make sure they are named correctly, HomeSegue, HeartSegue and CogSegue.

You should complete this process for your remaining two UIViewControllers and your finished UIStoryboard should look something like this.

As you can see it is very simple to create your own custom transitions with very little code. I hope this helps you to create your own navigation items.

Is Apple unravelling?

There seems to have been a reasonable amount of discussion about Apple’s recent event expressing concern over the direction and message the company is trying to convey. After re-tweeting Jolie O’Dell’s article it was suggested by a number of people that I was subscribing to what was essentially flame baiting?! While I explicitly stated I didn’t agree fully with tone of the article I do think there are some things that we should be rightly concerned about as avid Apple users.

My first thought was, have I been sucked in by the controversy of this article or has it rightly resonated with something deeper that has concerned me about Apple’s direction? So I went back through and looked at O’Dell’s article and considered comments made by Matt Thomas.

Thomas focuses on, new iMac and new iPad, thinnovation and revolutionary, and the various abominations of the apple logo that have gone on over the years to make the point that this is not an unravelling but merely more of the same. Does this make it acceptable? In my mind it does not, now I understand that it makes a convent argument in the Jobs vs Cook debate however, my concern comes with the fact that Cook has repeated what I see are mistakes. Good leaders should learn from the mistakes of others as well as those they make on their own.

I think it would be safe to say I hated the tie dye logo. It is clear that it has been designed to hark back to the earlier rainbow Apple Computer icon, playing to the feeling of the “same old Apple” which I can completely understand. However, I would have like to see a complete focus on a new and improved Apple to help Tim Cook move out of the shadow of Steve Jobs however, in my mind it works to do the very opposite.

Most like O’Dell have jumped on these presentation issues and written Tim Cook off (far too early in my opinion) but what seems to be a real cause for concern for me is what was actually presented. First the new Apple TV interface is horrendous.

It wastes screen real estate (only five buttons are visible on a giant screen TV), it has garish colour combinations, irregular and inconsistent UI elements/fonts.

The next abomination is iPhoto! I would quite honestly say it is one of the worst apps I have used! The settings tab that is actually context aware so depending on which tab you are on before tapping the settings tab will result in a different set of settings being provided. Scrolling is unbelievably jerky (on iPhone 4) and when you scroll quickly you see huge glitches when the interface has to catch up with your interaction. In general iPhotos inconstancy in design, its complete disregard for Apples own human interface guidelines and the amount of bugs make it a terrible all round user expereince.

With disappointment in 2 out of the 3 major announcements (and the iPad was a little underwhelming most people expected what we got) I can see why questions are being asked.

Is Apple unravelling?
I am not of the opinion that Apple is in fact unravelling, instead I think this is the understandable recalibration of a ship under new guidance. I do think Tim Cook has to move out of the shadow of Steve Jobs, he is not the charismatic innovator that Steve Job’s was. Instead he is the reliable, shrewd businessman upon which a solid business can prosper. He should continue to play to his strengths, after all he has held one of the most important positions at Apple for almost a decade under Job’s.

Hashing for privacy in social apps

Earlier today Matt Gemmell posted a really good article explaining hashing and how it can be used for privacy. The basic premise of the article is that data need not be stored in its raw form to enable comparisons to be made. This is a direct response to the recent discovery that the Path social networking app uploads the user’s entire iPhone address book to its servers.

I felt a little demonstration that you can do yourself might help illustrate Matt’s point and give people a better understanding of what he is talking about. As Matt mentioned there are many different hashing algorithms however the one most used (or at least the one I use the most) is called Message Digest 5 (md5 for short). You can read more about md5 here however if you accept that hashing algorithms change personal information into “Gibberish” then you do not need to understand the details of the algorithm to see this in practice.

For those of you with a Mac it is relatively straight forward for you to md5 text. Go to Applications and open up Terminal (this is where you can feel like a geek) if you type

md5 -s "some_text"

you will get

MD5 ("some_text") = 32d3f9b84bf99ae5faecc315d389c894 

where 32d3f9b84bf99ae5faecc315d389c894 is our “Gibberish” representation of “some_text”. As an alternatively to using Terminal, if you want to generate an md5 for a piece of text you can at this website. Alright lets get started using Matt’s example to walk through how to use hashing for privacy.

Bob is a member of Path, a social networking site. His address book contains 2 friends Jane and John. Jane’s email is jane@hashingexample.com and John’s email is john@hashingexample.com. When Bob joined Path the Path application uploaded the emails of both Jane and John. However following advice from a Matt they decided to use hashing to protect the privacy of their users. So before uploading the email addresses they used md5 to hash them, resulting in the following,

  • md5(“jane@hashingexample.com”) = “3e706175a85e3bc0a4dd52317d87285d”
  • md5(“john@hashingexample.com”) = “65e2d14a9b1ec95f06730d7956c90e65″

Now the Path client uploads and stores only the resulting hashes (try hashing these emails yourself, you should see that your Gibberish will match mine).

Having heard Bob talking about Path Jane decides that she would really like to see what all of the fuss is about and signs up. Path ask for her own email address, jane@hashingexample.com, which she gives as part of the sign up process and they hash it to get 3e706175a85e3bc0a4dd52317d87285d. Now they search their database to see if there are any people with contacts that have this email hash, which they do. They find Bob from the uploaded hashes pulled from his contacts list earlier and recommend that since she appears to know him that they become “friends”.

I hope this helps add a little more to Matt’s original article and will allow some of you to try it out.

Note: As kindly pointed out by Richard Buckle MD5 has been considered broken for several years, in that pairs of documents can be created to create collisions. This means that two different strings can create the same hash which I am sure from the example you can see would be problematic. This also raises some serious security questions that I won’t go into here but you can find out on wikipedia should you be interested. Instead it is recommended that the SHA-2 hashing algorithm is used for security applications. If you would like to see this in action you can follow the previous example replacing the MD5 hashing algorithm with the following command,

echo "some_text" | shasum -a 256

iOS 4 & iOS 5 : Custom UIAppearance Tutorial

Having battled against the iOS API to theme my applications I was extremely pleased when iOS 5 introduced UIAppearance, allowing individual user interface elements or entire classes of elements to be themed in a particular way. Recently one of our apps required support for iOS 4.3 so I had to go back to my previous (more painful) method. I thought it might be useful to document both these methods to help anyone who might face a similar pain so hope this helps.

iOS5
In this example I am going to focus on theming a UINavigationBar but the principles in this article are the same for other elements. First lets look at how to change the background image of an individual UINavigationBar,

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav bar.png"] forBarMetrics:UIBarMetricsDefault];
}

However, if you want to have the same background image on every UINavigationBar within the app this can be problematic, you will have to set the background image in several places depending on where you create all of your UINavigationBars. Instead you can use the UIAppearance of the UINavigationBar.

[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"nav bar.png"] forBarMetrics:UIBarMetricsDefault];

This will theme every UINavigationBar element with the nav bar image, and the best thing is that in iOS 5 every UI component (or at least all of those I have used) implement UIAppearance so you can use this technique to theme all of your UIBarButtons, UIToolbars or any set of components you need to.

For most of us this will be the way we theme things from now on however, for some of us we still feel the obligation (or need) to support older versions (at least in the short term) so here is how to achieve the same results in iOS 4.3.

iOS 4

Objective-C categories, allows you to add additional functionality to objects that you are not the original creator of. You don’t even need the source to the original classes. Using this method you can override the drawRect method and customise the appearance of all of the UINavigationBars.

@implementation UINavigationBar (UINavigationBarCategory)
 
- (void)drawRect:(CGRect)rect {
    UIColor *color = [UIColor blackColor];
    UIImage *img  = [UIImage imageNamed: @"nav bar.png"];
    [img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.tintColor = color;
}
 
@end

Using Objective-C categories can be a useful and convent way of theming UINavigationBars and UIToolbars etc however, they do alter the appearance of all instances of this so it can throw off the appearance of other UI components that are part of the SDK. For example I recently looked to change the background of a UITableView with a category which worked well after I set the UILabels on the UITableViewCells background colour to clear. However, when I launched the UIImagePickerController the background was also changed on this and I had no easy way of setting the UILabels in its cells to have a clear background so the view looked horendus. Instead of using categories I created a base UITableView class that I extend to ensure that each UITableView is themed correctly.

Sources
This is a really useful resource that I drew from to theme my user interfaces in iOS4
Ray Wenderlich: iOS 5 User Interface Customisation

Teaching Style: David Foster Wallace’s Syllabus

Earlier today John Gruber posted an interesting link on Daring Fireball to an article by Katie Roiphe on David Foster Wallace and his teaching style that really resonated with me. Before I expand on my thoughts here is what was posted.

David Foster Wallace’s Syllabus
“If you are used to whipping off papers the night before they’re due, running them quickly through the computer’s Spellchecker, handing them in full of high-school errors and sentences that make no sense and having the professor accept them ‘because the ideas are good’ or something, please be informed that I draw no distinction between the quality of one’s ideas and the quality of those ideas’ verbal expression, and I will not accept sloppy, rough-draftish, or semiliterate college writing. Again, I am absolutely not kidding.”

Katie Roiphe, writing for Slate:

Of course, this is not the part of teaching that most people pour their hearts into. It’s just a syllabus! Wallace is bringing to the endeavor rigorous Salingerish standards of not lying, or not being phony, that would reproach other more ordinary people if these standards did not border on parody, and were not expressed in such a good natured and honorable way.

with John Gruber adding,

“Don’t just go through the motions. Don’t accept dogma. Look for ways that you might be wrong, don’t look for ways to prove you’re right. Think. Express your thoughts with as much precision and care as you can muster.

That’s why Wallace’s work serves as a beacon, a yardstick, for my own.”

My Thoughts
Having lectured extensively myself this is such a refreshing take on teaching. Learning has become extremely prescriptive and is generally delivered in the same mundane way. Individuals are as much to blame as the organisational establishments they work within, wether they be schools, universities or corporate environments. A focus on, exams or league tables as a measure of success has become the norm. However, many success stories are lost with this metric. This may seem like a strange interjection this early on but stay with me for just a second. During John Gruber’s keynote at Singleton he made reference to the following Stanley Kubrick quote to define the difference between Apple and Microsoft,

“Sometimes the truth of a thing is not so much in the think of it, as in the feel of it.”

In essence he was describing how we should consider these companies and the underlying truth engrained in their products and corporate culture. With Microsoft products he suggests that the truth of them is in “the think” of them, to understand the true nature of a Microsoft product you can lay it out as a bullet point list highlighting features etc. With Apple products the truth lies in “the feel”, and you can no better explain why you feel affection for your iPhone/iPad or aspects of the user experience in the same way you cannot explain why you feel affection to the people you love, it is very emotional.

In todays learning establishments we are taking the Microsoft approach to measuring the success of our students when instead we should be taking the Apple approach. Often the choice of the metrics that we measure our students learning by is not based on what is best for the student or students, instead the focus remains on what is easiest for our teachers; which is a very sad indictment of the situation we find ourselves in. While I agree with David’s approach to engaging and encouraging the creative process I think he could go yet further. In his Syllabus he “draw[s] no distinction between the quality of one’s ideas and the quality of those ideas’ verbal expression, and [he] will not accept sloppy, rough-draftish, or semiliterate college writing. I would suggest that this expression of idea should not be constrained to writing. The ability to express ideas differs dramatically between individuals, with each preferring different styles, verbal, written, graphical, kinaesthetic etc. While more difficult to assess this is something we should strive toward in every Syllabus for learning we ever put together.

One final thought that continously gets me down particularly when watching other lecturers is the arrogance that comes with the position. Many teachers have either forgotten or do not believe that our students have as much to teach us, as we have to teach them, the learning process is a two way streak. All we can claim to bring to the party is experience, that we hope to pass on.