Subscribe ( RSS )

iPhone Programming Tutorials


GPS Where To Go? Find Points of Interest using GPS.
Got It!
Intimate Secrets
Dynamic photo effector
Where To Eat? Find restaurants using GPS.
Advertise Your App Here
 

iPhone Programming Tutorial - Using A TabBarView To Switch Between Views

In this tutorial I will show you how to develop a UITabBarController which contains a custom UIView from one of the tabs and a UINavigationController with a UITableView dictated byUISegmentControl in the second tab.

This tutorial was contributed by the user cruffenach.  You can check out his website at http://losectrl-gaincommand.com.

If you would like to contribute a tutorial to iCodeBlog.com, contact me brandon@icodeblog.com

The final product of this tutorial should look something like this:

Setting up the User Interface

The first thing we need to do is open up MainWindow.xib. This will launch interface builder and show what our UITabBarController looks like. In the first tab we see a custom UIView that can be changed however we like, but we are more concerned about the second tab.

Clicking on the TabBarController within the instance window of interface builder and then looking to the Inspector will let us set the type of view controller which each tab will be displaying. The first tab uses a ViewController, and for the second tab we want to use a Navigation Controller type because we will be utilizing the navigation bar to hold our segmented control.

Once in the second tab, we will drag a UISegmentedControl out of our library and onto the navigation bar. The UISegmentedControl will change its look depending on the context you place it in. Here we will essentially be making the TitleView of the NavigationItem a UISegmentedView. This will be important when we get into our code.

With that done, we click on the view of the second tab and set it to be identified as a SegmentedTableViewController or type UITableViewController. We will create that class later in xCode. With that set we drag in a UITableView and connect its DataSource and Delegate methods to our view controller which has now been defined as SegmentedTableViewController. That is all we need to do in interface builder.

Going into xCode we do not need to modify any of the generated classes, however we do need to create a new one. Hit Apple + N and create a new UITableViewController called SegmentedTableViewController. This class will have the datasource methods for a UITableView all ready.

In this class we are going to need an int called selectedSegment, this will be updated to represent which segment is selected. Within the main we need to uncomment the viewDidLoad method and enter the following code.

This code gets the UISegmentedControl from the titleView of the navigationItem, and modifies it to add an action so that when the selected segment changes a method called segmentAction is called. The selectedSegment int is set to the initially selected segment and the titleView is reset with the modified UISegmentedControl.

Next we need to create the method which the UISegmentedControl will call. Here is the code for that method, following the same syntax as a IBAction Method.

This code takes the sender which will be out UISegmentedControl and gets the new selectedSegment from it and sets out variable to that value. Finally it tells the UITableView that something has happened and the data in the table needs to be reloaded.

The final steps is to tell the UITableView that is will be displaying 100 cells and telling the returned cell for each row to have some text which is a product of the selected segment. I chose to have each cell read “I AM CELL (selectedSegment * indexPath.row)”. This essentially means that when segment 0 is selected every cell will read.

I AM CELL 0

When segment 1 is selected the cells will read.

I AM CELL 0

I AM CELL 1

I AM CELL 2

….

When segment 2 is selected the cells will read.

I AM CELL 0

I AM CELL 2

I AM CELL 4

I AM CELL 6

….segment. I chose to

The code to make this happens is…

You can download the source for this tutorial here. icodesegmentcontrol

 

27 Responses

Peter Says:

October 13th, 2008 at 4:28 am

Nice tutorial.. thank you!

MacE Says:

October 13th, 2008 at 7:18 am

No source??? It’s easier to follow when you have a xcode project source file to follow by.

Jason Says:

October 13th, 2008 at 10:29 am

Ok, the tutorials on the site are great, but you need to stop putting screenshots of code up and put up the actual text. Very annoying.

Elyézer Mendes Rezende Says:

October 13th, 2008 at 11:46 am

Nice tutorial.

Brandon Says:

October 13th, 2008 at 11:48 am

@MacE,

Sorry about that. The source is now posted.

@Jason,

There is a reason for not putting the actual code in text. If people just copy and paste the text, it is much harder to learn what you are doing. I have gone through many tutorials where I just copied and pasted and didn’t get anything out of it.

It’s like when you take notes for school. You can’t easily commit the stuff to memory without physically writing it down.

Paul Says:

October 13th, 2008 at 11:01 pm

Hello,

I am new to iPhone programming, but I wonder if [segmentControl release]; is OK in viewDidLoad, since we did not actually create an object there, just obtained a pointer to an existing object.

Collin Ruffenach Says:

October 13th, 2008 at 11:49 pm

Hey Paul,

You are correct, actually both the [segmentControl release] from –(void)viewDidLoad and -(void)segmentAction:(id)sender should be removed. Nice catch!

David Says:

October 14th, 2008 at 12:21 am

Fully agreed. Actually typing in the code helps the mind retain.

Thanks for the tutorial.

One thing though… why are we releasing data that we only get a pointer to?

For example…

UISegmentedControl *segmentControl = sender;
selectedSegment = [segmentControl selectedSegmentIndex];

[segmentControl release]; // why do we need to do this? Does sender retain???

Thanks! Keep the tutorials coming, they’re great!

David Says:

October 14th, 2008 at 12:26 am

Ah, never mind my above comment. It was caught by Paul while I was writing my comments up.

MacE Says:

October 14th, 2008 at 5:07 pm

@Brandon

Thanks for posting the source. That helps me a lot! Thanks again. Nice Tut.

Jazzgenx Says:

October 15th, 2008 at 6:17 pm

@Brandon

DUDE…you dont know what u have done!!!!….. you are AWESOME!!!…i was having this problem since the past few days….and this tutorial was just what i needed….

just a tiny feedback..”ask people to add the core graphics framework because xcode with it;s default config gives a GRectZero error..

thanks Again

jase Says:

October 16th, 2008 at 12:17 am

Great tutorial!

Helped me a lot, but when I did this tutorial, after hitting the Number*2 button, the entire Segmented control would disappear. I had to comment out this line in order for it to remain visible.

// [segmentControl release];

Steve Says:

October 16th, 2008 at 4:58 am

Thank you very much. I’ve been looking high and low for a simple approach to this problem and this is by far the easiest to follow.

Daniel Says:

October 17th, 2008 at 7:32 pm

I have three questions about viewDidLoad.

First, why do we need this line:

self.navigationItem.titleView = segmentControl;

If segmentControl already points to the same object then why would you need to do this assignement. Arn’t they already equal? It seems like this won’t hurt anything, but do you need it? I pulled it out and everything seems to run fine, but I wanted to ask anyways.

Second, people are saying that you do not need to release the segmentControl, as in:

[segmentControl release];

Coming from a C/C++ background it makes sense to me that you don’t need this; however, from what I am reading I am not sure that that is the case. I can definitly be mistaken, but isn’t the retainCount incremented with the statement:

UISegmentedControl *segmentControl = …

If so, then wouldn’t the release be needed? I’m just trying to understand the way the retainCount works in this instance.

Third, what is the advantage of creating the selectedSegment class property. Why not simply ask the UISegmentedControl directly each time you need to know which segment is selected. Is there a significant runtime advantage in speed or something? Just wondering at what times I would or would not create these types of intermediate variables rather then talking directly to the objects in question (like the UISegmentedControl object).

Thats it for me. Thanks for the help.

Daniel Says:

October 18th, 2008 at 4:38 pm

Just to clarify my third question above. Why not get rid of selectedSegment and do something like this within the TableView function:

UISegmentedControl *segmentControl = self.navigationItem.titleView;

cell.text = [NSString stringWithFormat:@"I AM CELL %d", ([segmentControl selectedSegmentIndex] * indexPath.row)];

Is it because this solution involves more runtime resources then simply tracking the selectedSegement in a class variable?

Daniel Says:

October 18th, 2008 at 4:40 pm

Also, let me add a forth question. Can someone explain how to resolve the compiler warning for this line of code:

UISegmentedControl *segmentControl = self.navigationItem.titleView;

Normally code can be rewritten to eliminate warnings. Is there some way to do so in this case?

Ok…that is it for me. Those 4 questions and I’m good to go. Thanks.

Daniel Says:

October 19th, 2008 at 6:16 pm

I figured out question number 4. I think that it is a problem of type casting (so to speak). If you do the following it will cast the types properly.

UISegmentedControl *segmentControl = (UISegmentedControl *) self.navigationItem.titleView;

So, any ideas on the other three questions?

Daniel Says:

October 19th, 2008 at 6:24 pm

And for my third question. You can get rid of selectedSegment all together and just put this line into tableView instead:

cell.text = [NSString stringWithFormat:@"I AM CELL %d", ([(UISegmentedControl *) self.navigationItem.titleView selectedSegmentIndex] * indexPath.row)];

Since the UISegmentedControl already exists then there shouldn’t be any runtime advantages for memory usage, and since we are just dealing with pointers then this should also be comparable in runtime speed (though maybe there is some small referencing degradation).

So, I am still not sure whether there is any advantage or disadvantage of one approach over the other. But this single line seems to make things easier for me to follow then having that extra variable declared in my class (selectedSegment).

Any thoughts on the subject? Anyone? Maybe I should be posting this in the forums.

Brandon Says:

October 20th, 2008 at 11:27 am

@Daniel,

I’m not sure why the author of this tutorial hasn’t responded to your questions. I will email him later today and let him know…

Collin Ruffenach Says:

October 20th, 2008 at 3:29 pm

@Daniel,

Hey sorry about the long response time. Wow lots of questions. I simply chose to code it the way I coded it, the [segmentControl release] statements should be removed as I stated earlier, and as for your more optimized code, I believe that should work as well, this essentially brings us into the topic of hope flexible Objective C can be when you get into it. It is really up to the programmer. Thanks for your interest and keep on coming back to iCodeBlog!

Daniel Says:

October 21st, 2008 at 6:58 pm

Cool, but could you confirm for me that the assignment was not needed (question 1). I just don’t want to assume that it is not needed if there is actual a reason for it. Was this line needed in viewDidLoad?

self.navigationItem.titleView = segmentControl;

I think that that is the only question that I have not confirmed. If I pull it out it does run properly, and I think it is not needed, but I just want to confirm that that is the case. Maybe there is something going on with that line that I do not understand and I don’t want to miss anything. Thanks.

cjr Says:

November 13th, 2008 at 4:23 pm

Hi,

Really useful tutorials. I think you mentioned in an early tutorial that you weren’t completely happy with your iPhone simulator screenshots. Here is a tip from David Pogue’s Mac OSX Missing Manual:

Press Shift-Apple-4
Hover over iPhone simulator window
Press the Space Bar
Press the mouse button

The screenshot will appear on your desktop.

Brandon Says:

November 15th, 2008 at 1:01 pm

@cjr

Sweet thanks for the tip!

N Says:

November 21st, 2008 at 1:33 pm

“I simply chose to code it the way I coded it”, so uh, I guess you don’t know the answer.

Tom Says:

December 3rd, 2008 at 2:12 pm

Collin, thanks for the really useful tutorial.

I found that compile warning annoying so I looked for a different way to get this to work.

Made the following changes to the code:
1) Added an IBOutlet for the segmented control
2) Converted the segmentAction method to an IBAction
3) Commented out the viewDidLoad method. the segmented control starts with segment 0 selected by default.
3) Made the necessary connections in IB: Connected the segmented control to the segCtrl outlet in the TableViewController. Connected the valueChanged event in the segmented control to the segmentAction in TableViewController.

I think this is cleaner but, as you say, there’re always several ways to implement something. Not to mention the fact that it’s always easy to tinker with code that someone else got working first.

Thanks, again, for putting this together and publishing it. Saved me a lot of time.

Here are the relevant code fragments:

@interface SegmentedTableViewController : UITableViewController
{
int selectedSegment;
UISegmentedControl *segCtrl;
}

@property (nonatomic, retain) IBOutlet UISegmentedControl *segCtrl;

- (IBAction) segmentAction:(id)sender;

@end

———————————————————–

@implementation SegmentedTableViewController
@synthesize segCtrl;

// - (void)viewDidLoad //Not necessary, I think.

-(IBAction)segmentAction:(id)sender
{
selectedSegment = [self.segCtrl selectedSegmentIndex];
[self.tableView reloadData];
}

Steve Wond Says:

December 18th, 2008 at 8:32 am

Great tutorial but you should rerecord it without the “HUH” “HUM” that you interject between every few words.

Tylor Says:

January 2nd, 2009 at 9:57 am

Thanks! Great tutorial. I liked the video a lot. It was a bit fast and I wouldn’t have gotten it hadn’t I already known a little bit about Xcode. But luckily I was able to follow along. Keep up the great work!

Leave a Reply