iPhone App of the the moment: Here, File File!

With Here, File File! you gain remote access to one or more of your Macs even if you’re not in your local network: Just download the companion OS X App from the official website, install, and spawn a server which will talk to the iPhone App. You can bind it to your Mac’s local IP address or, even better, use it in combination with a dynamic DNS hosting service like DynDNS.com.

What really kicks ass is that you can stream music and movies from your Mac right to your iPhone without having to sync your content via iTunes. Besides, it has great support for all kind of document file types, Spotlight search, and - it’s a real beauty.

 

Pricing: $9.99 / 7.99€ - Buy at the App Store.

Filed under  //   appreview   iphone  

OMG, it has no multitasking!

I have one advice for all those people that are complaining about the iPad’s lack of multitasking though I can’t really tell anything precise due to the confidential status of Apples new beta release of the iPhose OS 3.2, but, if you can: take a look at the developer resources, especially the “iPad Programming Guide”, page 28.

Not only that it introduces a whole new exciting feature to the iPhone OS, but it also has the word ‘Multitasking’ written all over it.

Seriously, do you really think the iPad with it’s “blazing” new 1GHz Apple A4 chip (probably made out of Steve Jobs’ blood and the tears of 100 unicorns) wasn’t technically capable of executing two or more Apps at once? C’mon!

Multitasking isn’t just a simple feature, if you consider it to be engineered really good, both on the iPad AND the iPhone. It’s not just about throwing some task manager in, it’s about having an “intelligent” and sophisiticating multitasking architecture combined with a great user experience.
Take for example the Android plattform. They have a bunch of task-killing apps (like this one), but do you really call this a great user experience, to launch an app in order to kill some other apps? I don’t think so.

It’s like the iPhone’s “Cut, Copy & Paste” feature, which was part of the latest major update of the iPhone OS. It was not just about having some fancy UI for copying text and pictures. I think it required a lot more work “under the hood” that simply couldn’t be shipped as part of a minor 2.x update.

So, my prediction is that multitasking will be part of the next major update of the iPhone OS that will be introduced at WWDC 2010 or maybe even earlier. Try to relax in the meantime ;)

Filed under  //   ipad   iphone   stevenote  

The need of iPhone background apps.

Yesterday I tried some new apps from the iPhone jailbreak community on my iPod touch 2G (codename: sandbox). Some days ago, Leo from fscklog posted some quite interesting stuff at his blog (englisch translation). One of those apps was ProSwitcher by @rpetrich and @chpwn.

They’ve implemented a way to switch between different active apps by using the same approach of Palm’s webOS: You can flick through your running applications via activity cards. Of course, non of the apps you bought at the AppStore are able to run in background per default. That’s why ProSwitcher uses Backgrounder (another jailbreak utility) for sending apps into background mode. Even though I’m not a big fan of this whole jailbreak stuff, I must admit that ProSwitcher is very well implemented and runs smoothly on my device. It’s actually pretty fun to play with.

See the following demo on YouTube to get the idea.

One of the first apps I tried was the latest and greatest version of the Last.FM app. Now I could listen to my stations while browsing, reading etc. - awesome!

But after that I couldn’t really imagine any other apps that really need to run in background. So I gave I shout at the Twitter universe and received some feedback, even from one of ProSwitcher’s developers.

Sure it’s a nice thing to have your favorite IM app or your favorite game running in the background so it can be easily interrupted for some other action like sending an SMS, making a call, writing a note etc. but, like I said, those apps don’t need to necessarily run in background. For IM apps you got the Push Notification service that was introduced in iPhone OS 3.0. Apple may introduced it as some kind of workaround for the missing background apps but I think it actually worked out pretty well.

On the other hand you have a lot of great apps that are developed almost as if they were capable of running in the background. Tweetie2 is a good example. If you’re interrupted (e.g. by a phone call) and return back afterwards, it really feels like the app never quit. Loren Brichter really did an awesome job on that. With the iPhone 3G[S] and the new iPod touches I feels even more naturally because of the faster processors and the reduced startup time of almost every app.

But anyway, it’s a fact that iPhone apps are able to run in the background. Safari does, Mail does, the iPod app does, so why is Apple holding this feature back to its developers? My personal opinion: They just want to do it right.

It’s kinda like the introduction of the official iPhone SDK no more than one year after releasing the original iPhone. Just until today, many people think that Apple didn’t want to give away their APIs and only did so because of the pressure of the developer community. Bullshit! It was in the pipe for quite a long time but they just want to do it right before releasing it.

Background apps are coming (maybe in iPhone OS 4.0) but…

  • Will the feature be made available for really every app that will be submitted to the AppStore? And if not, who will make the distinction?
  • What about memory and battery consumption? Does it require a new / improved memory and energy management?
  • What about the design of the UI for the end-user?

I think to get a satisfying answer to all those questions Apple has to dig deep under the hood of the iPhone OS. But until then, I’ll regard ProSwitcher more like an (awesome) experiment than a real solution.

For those who are curious: You can browse ProSwitcher’s code at github.

Filed under  //   iphone   jailbreak  

How to embed a navigation controller inside a tab bar controller (Part 2)

There was a tremendous feedback for my original article about embedding a navigation controller inside a tab bar controller. Thank you guys :) I really appreciate that. I’m really sorry I’m a bit late with that but I had a ton of work in the last weeks. By far the most requests were about using a table view controller instead a normal subclassed view controller. I’ll show you a little update of my code where I’ve put a table view controller in the second tab that is displaying some dummy data. Actually it’s really pretty simple.

So fire up your Xcode IDE, load in “Tabs” project and let’s get started ;)

First of all, create a subclass of UITableViewController and name it “MyTableViewController”. After that create a property for the data that will be shown inside the table view. Here I chose a simple NSArray and named it “tableData”.

#import 


@interface MyTableViewController : UITableViewController {
  NSArray *tableData;
}

@property (nonatomic, retain) NSArray *tableData;

@end

Head over to the MyTableViewController.m file and change some of the methods that were generated for us. In order to create and initialize our tableData object with some dummy data, we’ll add the following line to the viewDidLoad: method

- (void)viewDidLoad {

  [super viewDidLoad];
  tableData = [[NSArray alloc] initWithObjects:@"foo", @"bar", @"baz", nil];
}

In tableView:numberOfRowsInSection: return the actual number of elements of tableData.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

  return [tableData count];
}

Finally, in tableView:cellForRowAtIndexPath: configure the fetched cell by setting cell.text to the corresponding object (that happens to be a NSString) of the tableData array

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  }

  // Set up the cell...
  cell.text = [tableData objectAtIndex:indexPath.row];

  return cell;
}

After you have accomplished that, create a new XIB file called “ThirdView.xib”, open it in Interface Builder (IB) and simply drop a UITableView onto the empty view. Set File’s Owner to MyTableViewController and also make it the table views delegate and data source by control-dragging from the table view to File’s Owners and connecting the appropriate outlets.

Screen01

After you saved your ThirdView.xib, open your MainWindow.xib in IB. In the little window titled “MainWindow.xib” expand the Tab Bar Controller entry by clicking the little triangle left to it (if you don’t see it, make sure you chose the list style display) and also expand the My Navigation Controller entry that lives inside the Tab Bar Controller entry. Here you should see three entries: Navigation Bar, Second View Controller and Tab Bar Item.

Screen02

A UINavigationController holds a reference to a view controller that he actually takes care of. In this case it’s our SecondViewController, a simple subclass of UIViewController that manages a view that is prompting the words “Can I haz navigation?” (I assume you remember that from the original article). In order to have our navigation controller take care of our freshly created MyTableViewController, we have to change the Second View Controller entry. Select it, press +4 to head over to the identity inspector where you should see the Class entry set to “SecondViewController”. Change that to “MyTableViewController”.

Screen03

In addition to that, change the NIB Name in the attributes inspector (+1) from “SecondView” to “ThirdView” (to ensure that our MyTableViewController fires up our ThirdView.xib). If everything went well, the whole MainWindow.xib setup should look like this

Screen04

Well… that’s it ;) Save all your unsaved files, return to Xcode and choose build and run:

Screen05

I hope this little update answers most of your questions. If you still have problems or questions, please drop me a line. I’ll try to answer as quickly as possible ;)

Filed under  //   development   iphone   tutorial  

Customizing table view cells for fancy user interfaces

Table views are not only about displaying arbitary data in form of a list. Today, I will show you some little tweaks to create some nice user interfaces with the help of table views and their cells. I’ll present some tactics I’ve learned from the CocoaCast podcast made by Boris Klaydman. If you don’t know it yet, I recommend you to take a look. Those guys do an amazingly good job ;)

Some theory about table views

In order to use table views in your iPhone app, you take adventage of the UITableView class in combination with a subclass of UITableViewController. The controller helps you to bring the table view to life by acting as it’s data source. The table view will ask it’s data source, “What should I display at row xyz?”, and the data source will give him the answer. A UITableView consists of cells, instances of UITableViewCell or it’s subclasses. You’ll use the subclasses if you want to present cells with custom behaviour to the user.

Okay, enough theory – let’s fire up Xcode for some table view fun ;)

Here’s a picture of the complete user interface that we are about to build:

Screen01

Pretty neat, huh?

Start a new project

In Xcode click File > New Project, choose the Navigation-based Application as template for our project and name it “TableViewFun”. This will create a working application with a table view that lives inside a navigation controller. We won’t develop it from scratch this time since we want to concentrate about the customization of our table view cells. But if this is the first time for you working with UITableView I’ll briefly scan through the code and explain what has been done for us.

The most important part is the UITableViewController subclass that is named “RootViewController” in this template. When you open RootViewController.m, you’ll see a whole bunch of code that has been generated for us. The interesting part of that is the section marked as #pragma mark Table view methods. The following four methods are the data source methods that are used to set up our table and fill it with content:

numberOfSectionsInTableView:

Here we’ll tell the table view how many sections we want to display in our table.

tableView:numberOfRowsInSection:

This one will tell the table view how many rows live in each section. This can be some static value(s) or, considering you’ll want to show the contents of an NSArray in the table view, it could be the return value of a method call, e.g. [myArray count]

tableView:cellForRowAtIndexPath:

The actual table view cell for a given index path. An NSIndexPath is a C-struct that helps you navigate through a table view by indicating where you are, e.g. section 1, row 5. Because memory is limited on a mobile device like the iPhone, we’ll try to reuse cells in this method instead of always creating new ones. We will come to that in a minute ;)

tableView:didSelectRowAtIndexPath:

This will trigger some custom action for selecting a table view row. In most cases this would be pushing a new view controller onto the navigation stack for drilling down a table view, but we will use it for some other purpose.

There are some more (optional) data source methods defined in the UITableViewDataSourceProtocol but we won’t need them at this time. Feel free to browse the Apple docs if you want to know more about the remaining methods.

Some interface work

Open RootViewController.xib for some minor changes concerning the table view. It should open a view with an embedded table view. Click the table view to select it. In the Attributes section of the Inspector (+1) choose the “Grouped” style instead of the plain one. Save and return to Xcode.

Since this is all about customized cells, we’ll have to create them too. You could do this programatically, but I’ll present the way you would do it with the help of Interface Builder (IB). Control-click the Classes folder in “Groups & Files”, choose “New File” from the context menu and select “UITableViewCell subclass” from the “Cocoa Touch Class” section. Name that class TextFieldCell (this will be the cell holding a UITextField) and create the .h and .m files.

Now we’ll have to create the correspondig NIB (XIB) file. Right-click on the “Resources” folder, choose “New File”, create an empty XIB from the “User Interfaces” section of the iPhone OS group and name it “TextFieldCell.xib”. Open the file by double-clicking which will take you back to IB. Open the Library and drag a UITableViewCell onto the little window with both the “File’s Owner” and “First Responder” in it. Double click it and up pops another window which represents the table view cell. We’ll customize it by dragging a UITextLabel and a UITextField on it. Play around with their attributes until you have something like this:

Screen02

Set File’s Owner’s class to “RootViewController” and the UITableViewCell’s to “TextFieldCell”. In the Identity section (+4) for the table view cell create an outlet named textField for the UITextField instance you dropped onto our custom cell. Connect the outlet with the actual text field and define the outlet in TextFieldCell.h (e.g. by dragging it from IB to Xcode). Create and synthesize a corresponding property as well and don’t forget to release textField in the dealloc method. After that, create an outlet for our TextFieldCell named “textFieldCell” in RootViewController, connect it, create poperties, synthesize them and edit the RootViewController’s dealloc method.

TextfieldCell.h

#import 


@interface TextFieldCell : UITableViewCell {
 IBOutlet UITextField *textField;
}

@property (nonatomic, retain) IBOutlet UITextField *textField;

@end

RootViewController.h

#import "TextFieldCell.h"
#import "SwitchCell.h"


@interface RootViewController : UITableViewController {
 IBOutlet TextFieldCell *textFieldCell;
}

@property (nonatomic, retain) TextFieldCell *textFieldCell;

@end

After that we’ll create another custom cell, the one with an UISwitch in it. It’s pretty straight forward if you completed our first custom cell. So I assume you can do it on you own ;) Please name the UITableViewCell subclass “SwitchCell” and the corresponding XIB file “SwitchCell.xib”. The result should look like this

Screen03

SwitchCell.h

#import 


@interface SwitchCell : UITableViewCell {
 IBOutlet UISwitch *turnOnSwitch;
}

@property (nonatomic, retain) IBOutlet UISwitch *turnOnSwitch;

@end

RootViewController.h

#import "TextFieldCell.h"
#import "SwitchCell.h"


@interface RootViewController : UITableViewController {
 IBOutlet TextFieldCell *textFieldCell;
 IBOutlet SwitchCell *switchCell;
}

@property (nonatomic, retain) TextFieldCell *textFieldCell;
@property (nonatomic, retain) SwitchCell *switchCell;

@end

Adding the glue

Now that we have our customized cells it’s time to glue them to our table view. But first we have to do some more basic stuff. That is, to tell our table view the number of sections and rows for each section. For this example, we’ll have three sections (0, 1, 2). The first two sections (0, 1) will have one row each and the third section (2) will have three rows. The following snippet shows you how to do it:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

  switch (section) {
    case 0:
      return 1;
    case 1:
      return 1;
    case 2:
      return 3;
    default:
      // We'll never reach that case, but just to 
      // make sure that something will be returned
      return 0;
  }
}

Build an run our application and see what happens:

Screen04

Hmm, just what we wanted but it looks kinda naked, doesn’t it? What about adding some headers by implementing the tableView:titleForHeaderInSection: method:

- (NSInteger)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

  switch (section) {
    case 0:
      return @"Your name";
    case 1:
      return @"Turn me on";
    case 2:
      return @"Choose your destiny";
    default:
      // We'll never reach that case, but just to 
      // make sure that something will be returned
      return nil;
  }
}

Build and run… okay, that looks a lot better ;)

Screen05

But it’s quite obvious, that no of our custom cells were used. Instead, we’re presented the standard table view cells. In order to change that, we have to edit the tableView:cellForRowAtIndexPath: method. The default implementation is the following:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

 static NSString *CellIdentifier = @"Cell";

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
  cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
 }

 // Configure the cell.
 return cell;
}

As I mentioned before, it’s a good practice to reuse table cells instead of always creating new ones, cause this is always very expensive and it will create no good user experience. The default implementation uses a static identifier called “Cell” (or some other arbitary string) to reuse the table view cells. If no reusable cell could be dequeued, we have to create a new one. Here, an instance of the standard UITableViewCell class is used to create a new cell.

We have to decide which kind of cell has to be created for each section. In the first section of our table view we’ll need the TextFieldCell, in the second section we’ll need the SwitchCell and in the third and last section we will use the standard cells. We will load our two custom cells from their XIB files. In order to do that, we’ll call the loadNibNamed:owner:options: method from the mainBundle object:

[[NSBundle mainBundle] loadNibNamed:@"TextFieldCell" owner:self options:nil];

When doing like this our member variables textFieldCell and switchCell of the RootViewController class should be set to the right instances.

Take the snipped below for our implementation of tableView:cellForRowAtIndexPath: That’ll do exactly what we want.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

 UITableViewCell *cell;

 switch (indexPath.section) {
  case 0:
   cell = (TextFieldCell *)[tableView dequeueReusableCellWithIdentifier:@"TextFieldCell"];
   if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"TextFieldCell" owner:self options:nil];
     cell = textFieldCell;
   }
   break;
  case 1:
   cell = (SwitchCell *)[tableView dequeueReusableCellWithIdentifier:@"SwitchCell"];
   if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"SwitchCell" owner:self options:nil];
     cell = switchCell;
   }
   break;
  default:
   cell = [tableView dequeueReusableCellWithIdentifier:@"OtherCell"];
   if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"OtherCell"] autorelease];
     cell.accessoryType = UITableViewCellAccessoryNone;
   }
   break;
 }

 return cell;
}

Build and run and hopefully you’ll see the following:

Screen06

If your app crashes, check if you connected all your outlets properly. In most cases it has something to do with that ;)

So far, so good. Let’s take care of the remaining section. Here we want to implement a multiple selection view, kinda like the HTML checkboxes. First of all, create some selection items in the tableView:cellForRowAtIndexPath: method:

//...

 default:
  cell = [tableView dequeueReusableCellWithIdentifier:@"OtherCell"];
  if (cell == nil) {
   cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"OtherCell"] autorelease];
    cell.accessoryType = UITableViewCellAccessoryNone;
   switch (indexPath.row) {
    case 0:
     cell.text = @"Foo";
     break;
    case 1:
     cell.text = @"Bar";
     break;
    case 2:
     cell.text = @"Baz";
     break;
    default:
     break;
   }
  }
  break;

//...

Now, when the user taps one of these three cells, we want to represent a checkmark on the selected cell. That has to be done in the tableView:didSelectRowAtIndexPath: method:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

 // Retrieve the cell ...
 UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

 // For now we just take care of events
 // for the third section of the table view
 if (indexPath.section == 2) {
  if (cell.accessoryType == UITableViewCellAccessoryNone) {
   cell.accessoryType = UITableViewCellAccessoryCheckmark;
  }
  else {
   cell.accessoryType = UITableViewCellAccessoryNone;
  }
 }

 [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

Build, run and try “tap” one or more cells in the table view’s third section. You’ll notice a checkmark appearing at the right side, followed by a nice animation that indication that your selection has been completed.

Screen07

We’re done!

Uhm… actually we’re not really done yet ;) What about our text field? We had to implement the text fields delegate methods to complete it. Otherwise we could never dismiss the keyboard that appear when we tap onto the text field. But I’ll leave that as a little practice for you ;)

I hope you enjoyed my little tutorial about table view cells. I’m not quite sure if my way is to be considered as the best possible practice, but it works fine for me ;)

Filed under  //   development   iphone   tutorial  

How to embed a navigation controller inside a tab bar controller

It’s a commonly used design pattern in the iPhone world to combine tab bar and navigation controllers. In the official Apple developer docs you can find some clues how to solve this in a programmatically way, but you can only rarely find a good tutorial for doing this in Interface Builder (IB). So I’ll try to walk you trough all the steps for building a good application framework with one tab bar and one navigation controller.

If you like this tutorial, show some love and flattr it :)

Okay, let’s do this

First of all, launch your Xcode IDE, start a new iPhone window based project (we could use the tab bar based template but we want to create it from scratch) and call it “Tabs”. In “Groups & Files” expand the Resources folder and double-click MainWindow.xib to launch IB. Open the Library and drag a “Tab Bar Controller” onto the little Window named MainWindow.xib. The controller will appear on the workspace and a window with a tab bar layout will pop up.

Screen01

By the way: You can close the blank window layout, we won’t need it here ;) So far so good. We will now fill the two tabs that were created for us. But before that we need to create an outlet for the controller in the Tabs App Delegate object (that orange cube in the left window). We will name this outlet rootController and set the type to UITabBarController. Control-drag from the Tabs App Delegate to our Tab Bar Controller to connect the outlet.

Screen02

After that we return to Xcode in order to create this outlet in the TabsAppDelegate.h. Create a corresponding property as well (I assume you already know about Objective-C 2.0 Properties).

#import UIKit/UIKit.h

@interface TabsAppDelegate : NSObject 
{ 
  IBOutlet UITabBarController *rootController; 
  UIWindow *window; 
} 

@property (nonatomic, retain) IBOutlet UIWindow *window; 
@property (nonatomic, retain) IBOutlet UITabBarController *rootController; 

@end

Now, we will set and create two different controllers for the tabs: First, a subclass of UIViewController and secondly our long-awaited navigation controller ;) Head back to Xcode, control-click the Tabs project (the very first icon at the “Groups & Files” view) and choose Add > New File … Select an UIViewController subclass from the “Cocoa Touch Classes” section and name it FirstViewController (do not forget to create the .h file too). In addition to that create a FirstView.xib file in the Resources folder, open it in interface builder and build a simple view like the one below.

Screen03

In the Identity Inspector (+4) set the class of “File’s Owner” to FirstViewController and control-drag from “File’s Owner” to “View” to connect the view outlet. Save your work an switch back to MainWindow.xib. Now we have to tell the first tab that it has to care about our FirstViewController. In order to do so, select the first tab, open the Identity Inspector (+4) and set the tab’s class to FirstViewController. But what about it’s content? Switch to Attributes Inspector (+1) and choose FirstView from the NIB Name’s drop-drop down box. – What have we done here? We told the first tab to present the contents of our FirstView.xib. Finally, change the tab bar item’s title to “Simple View Controller”. If everything went well, the layout should look like this

Screen04

Time for our first launch, isn’t it? Almost. But first, we have to make some changes in our TabsAppDelegate.m

#import "TabsAppDelegate.h" 

@implementation TabsAppDelegate 

@synthesize window; 
@synthesize rootController; 

- (void)applicationDidFinishLaunching:(UIApplication *)application 
{ 
  // Override point for customization after application launch 
  [window addSubview:rootController.view]; 
  [window makeKeyAndVisible]; 
} 

- (void)dealloc 
{ 
  [window release]; 
  [rootController release]; 
  [super dealloc]; 
} 

@end

In [window addSubview:rootController.view] we add the view property of our root controller as subview to the window. Without that, our tab bar would never be seen on our device respectively our simulator. Save, build and run.

…drumroll…

Screen05

Woohoo! Everything went perfectly fine :) (If it did not for you, check your code and all outlets' connections). But now for the part you all waited for. Generally it’s almost the same steps but we have to watch out for some details. Create a new UIViewController subclass and name it “MyNavigationController” (don’t forget the .h file). Since we need an UINavigationController instead of an UIViewController, open MyNavigationController.h and change UIViewController to UINavigationController in the @interface directive.

#import UIKit/UIKit.h

@interface MyNavigationController : UINavigationController 
{ 

} 

@end

Since we will have to deal with the navigation controller programmatically to push and pop views, it’s a good idea to create an instance variable for it in our Tabs App Delegate class.

#import UIKit/UIKit.h
#import "MyNavigationController.h" 

@interface TabsAppDelegate : NSObject 
{ 
  IBOutlet UITabBarController *rootController; 
  MyNavigationController *navigationController; 
  UIWindow *window; 
} 

@property (nonatomic, retain) IBOutlet UIWindow *window; 
@property (nonatomic, retain) IBOutlet UITabBarController *rootController; 
@property (nonatomic, retain) MyNavigationController *navigationController; 

@end

Our navigation controller needs at least one view controller to display its contents. So go ahead, create another UIViewController named “SecondViewController” and also create a “SecondView.xib” with a layout similar to the first one.

Screen06

Save it and switch back to MainWindow.xib. Here comes the tricky part: Similar to the FirstViewController, select the second tab and set its class to MyNavigationController. After that, select the Tab Bar Controller and open the Attributes Inspector (+1). In the “View Controllers” section, change the term “Item 2” to “Navigation View Controller” (this will be displayed as the second tab’s title) and switch the class to NavigationController.

Screen07

Now we set the navigation controller’s root view controller: In the little MainWindow.xib Window expand the Tab Bar Controller. You should now see a Tab Bar icon and two sub controllers. Select the second one and expand it, too… Aaaaah, there it is! The navigation controller’s root view controller. Select it, set its class (+4) to SecondViewController and choose (+1) SecondView as NIB Name for the content. If everything went well, your layout should look like this:

Screen08

That’s it! Build, run and enjoy your creation

Screen09

As you can see, we built a sophisticated fully-fledged layout with less than 10 lines of self-written code. Feel free to play around with it or try to add some some more view controllers to the tab bar layout (it’s as simple as drag and drop).

Update

Due to huge demand I’ve added a second part of this tutorial that’ll walk you through the steps of having a table view controller instead of a normal view controller as second tab. Jump right into part 2

Filed under  //   development   iphone   tutorial  

NSXML and the iPhone

Today I tried to deploy the recent version of Twillo to my iPhone for debugging for the very first time (I received my activation key for the official iPhone Developer Program this morning ;)). Stupidly I didn't had in mind that almost all Cocoa classes for XML handling (especially NSXMLDocument, NSXMLElement and NSXMLNode) are not available on the iPhone plattform. Accordingly to Erica Sadun it seems that Apple has moved them into some private Framework that should not be accessed by "mortal" iPhone developers (maybe for some performance reason or something)

The NSXMLParser is still available though, but it seems for me that Apples way of "Event Driven XML Programming" is more a pain in the ass than a real alternative to NSXMLDocument and XPath. Luckily there's some promising project called TouchXML that delivers an Objective-C wrapper around libxml and uses almost the same syntax as the original Apple classes.

In the following days I'll try to integrate the TouchXML framework into Twillo and I'll keep you updated with the progress ;)

Filed under  //   frameworks   iphone   sdk  

About

Addicted to shiny apples, beautiful pixels, awesome code and electronic music.

TwitterFacebookFlickr