MikeTeo.net

A Software Technologist's Blog (Wanna Email Me?)

Simple iPhone Tutorial (Part 3)

August 31, 2008 By miketeo

With the completion of Part 2, the user interface of your application is almost ready. However, it does not serve much purpose since it does not interact with the users. In this last part of the tutorial, you will add in action handlers using addTarget API and @selector to capture user actions.

7. Adding Action Handlers Dynamically

We will now modify the OnOffTableCell and SliderTableCell classes to add in action handlers to handle events that are sent out when the user toggles the on/off switches or slides the bar in the slider control.

The (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents and the @selector calls allow you to add your own handlers to handle events for any UIControl classes.

OnOffTableCell.m

onofftablecell5

SliderTableCell.m

Build and run the application. Open the debugger console in your XCode (Run > Console). You will see the debugging output that are being logged in the console as you toggle the switches and move slider in your first tab view.

You can download Source Code Bundle now to see for yourself how it works.

8. Communicating Changes Across

(There is an additional source code bundle at the bottom of this post which contains the source code for communication changes using notification)

You have learnt how to capture control events. But a sophisticated application do not normally act on such events within a single function. Often, there are multiple points scattered over the application that are focused on handling these events within the scope of their use cases. How can you announce these events to other modules that may be interested in them? And how to make these announcements in a way that the sender and the listeners are loosely coupled to each to the extent that they aren’t even aware of each other’s existence?

The iPhone SDK (or more specifically the Cocoa framework) defines the NSNotificationCenter class to facilitate such communications. If you are familiar with the Observer-Observable design pattern, the concept of NSNotificationCenter should not be unfamiliar to you. By using (void)postNotificationName:(NSString*)notificationName object:(id)notificationSender API function, the sender can post notifications to interested listeners. Both parties just need to agree upon the common notificationName to use.

We will now adopt the following communication methodology on top of the NSNotificationCenter class.

  • Each UILabel objects on the second tab view will listen for notifications from NSNotificationCenter and will have its own functions to update their text value to reflect the conditions of the controls they are listening to.
  • The cell rows that contain the UISwitch objects in the first tab view will listen and announce changes in the UISwitch value. The first row will use the notification name “SwitchForRow0” while the second row will use “SwitchForRow1”. The notification names for each cell will be initialized in FirstTabViewController.m
  • The cell row that contains the UISlider object will listen and announce changes in the UISlider value over the notification name “SliderChanged”.

The following code snippets illustrate how the postNotification and addObserver API calls are being used to link up the SliderTableCell and OnOffTableCell classes to the SecondTabViewController class. Notice that the SecondTabView class contains no references to the cell classes. The addObserver calls only contain the notification names.

SliderTableCell.m

OnOffTableCell.m

SecondTabViewController.m

FirstTabViewController.m

firsttabviewcontroller5

Build and run your application now. The labels in the second tab view will reflect the actions you have made on the UISlider and UISwitch controls in the first tab view.

9. Conclusion

Hope you have fun following this 3-part tutorial. Drop me any comments (good or bad) on how I can improve this tutorial 🙂

  1. iPhone News » Blog Archive » Simple iPhone Tutorial (Part 3) Said,

    […] MikeTeo.net added an interesting post on Simple iPhone Tutorial (Part 3)Here’s a small teaserWith the completion of Part 2, the user interface of your application is almost ready. However, it d […]

  2. Rob Said,

    Mike,

    Thanks for this great tutorial. I used it to bootstrap my understanding of iPhone development. Something to note, your code sample for part 3 does not work for me (the first label and the slider label update, but the second does not). I’m playing with it to figure out what is going on, but thought I’d let you know. In my version (developed following your tutorial) I get the first toggle label working correctly, but the second and the slider do not update but just have word “Switch…” and “Slider…” in smaller font showing.

    Regards,
    Rob

  3. Tim Wood Said,

    In the last modification to OnOffTableCell.m, notificationName is never defined. Ending the method like this works:
    // TDW: missing in original
    NSString* notificationName = ( [title.text isLike:@”* 0 Row 0*”] ) ? @”SwitchForRow0″ : @”SwitchForRow1″;
    [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:control];
    }

    And, yes, it’s a little ugly… but title.text apparently has a hidden character stuffed in there and I’m too lazy to find the trim function…

  4. miketeo Said,

    @Tim:
    notificationName is defined as one of the attributes under OnOffTableCell class (refer to OnOffTableCell.h). The compiler will use this attribute and pass the compilation process. Nonetheless, I have modified the code bundle to explicitly use self.notificationName to improve the clarity of the code.

  5. Pata Said,

    What a clean and a “must have” tutorial you did. Thanks a lot ! Hoping others will come.

  6. Ryan Said,

    Mike, thank you for spending the time to build these tutorials. I have found many other short tutorials, but most of these show only a single concepts, or don’t tie things together as nicely as you have here. As an example, yours is the first I have found that clearly shows how to use multiple views on a screen.

  7. Elia Said,

    I enter from your examples because it helps me understand what’s going on when I go through it line by line. A couple of issues with the example as presented:

    1. notificationName is never defined in OnOffTableCell. For those typing like me, you will want to add NSString *notificationName and @property (nonatomic, retain) NSString *notificationName to .h file and @synthesize to the .m file.

    2. In FirstTabViewController.m, the notificationName needs to be assigned. Add the line as follows:

    – (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
    OnOffTableCell* cell = (OnOffTableCell*)[tableView dequeueReusableCellWithIdentifier:@”OnOffCell”];
    if (cell == nil) {

    cell.onOffSwitch.on = NO;
    cell.notificationName = [NSString stringWithFormat:@”SwitchForRow%d”, indexPath.row];
    }
    return cell;

    Mike, your source code shows this but your instructions do not.

    Thanks again! This short tutorial helped explain some things for me that the Apple Source Code couldn’t.

  8. miketeo Said,

    @Ella:
    The “missing” notificationName definition is specific to part 3 of the tutorial. I guess you are probably following the code blocks in part 2 which does not require the use of the notificationName.

  9. Andreas Said,

    Thanks. This is very useful.

    As Elia already pointed out, the line

    cell.notificationName = [NSString stringWithFormat:@”SwitchForRow%d”, indexPath.row];

    is missing in the description of section 8 in part 3 pertaining to changes in FirstTabViewController.m

    … and if Rob still wonders about the words “Switch…” and “Slider…” showing in smaller font – it’s the size of the label that needs to be bigger to show the full text – I ran into the same issue.

  10. m.graves Said,

    Thanks for this great tutorial. But I am getting a 404 not found page when trying to download the source.

  11. miketeo Said,

    @m.graves: My apologies on the bad link. It must have started when I reloaded the bundle recently. The link has already been fixed and tested to be working now.

  12. Pat Said,

    As others have pointed out, the notificationName variable is not defined in the tutorial (yes, it is in the code bundle if you download it, but it is missing from the tutorial text).

  13. miketeo Said,

    @Pat:
    Thank you for your feedback. I have replaced the OnOffTableCell code image, and added a new FirstTabViewController code image to address the missing notificationName issue.

  14. Chris Said,

    Thanks for the help here, but I’m having trouble making the table view “work” as follows.

    View comes up just fine in tab one as you have shown. However, I can’t seem to get the selection of a row in the table to push a new controller and then view a secondary (let’s say detail) view… Here is the code snippet that I’ve used… what am I missing? This code seems to work fine on a non-tab bar implementation, although that may just be me…

    thanks for any pointers. (Note, I’ve also tried didSelectRow….)

    – (NSIndexPath *)tableView:(UITableView *)tv willSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // Navigation logic — create and push a new view controller
    if (detailViewController == nil) {
    detailViewController = [[DetailViewController alloc] initWithNibName:@”DetailView” bundle:nil];
    }
    NSLog(@”Attempt to get details”);

    [[self navigationController] pushViewController:detailViewController animated:YES];
    return (nil);
    }

  15. Chris Said,

    I think I found the path to answer the navigation question, although I haven’t played with the code. Essentially you need to wrap the FirstTabViewController (UITableViewController) in a NavigationController and add the navigationController to the tabBarController…then the [self navigationController] would actually return the stack!

    There’s another good thread on this here:
    http://www.iphonedevsdk.com/forum/iphone-sdk-development/2447-tab-bar-controller-navigation-controller-tableview.html

  16. Veri Said,

    I just tried downloading the source bundle and it’s missing. You get an error 404. Don’t know if you are aware of it.

    Thanks for the tutorial.

  17. miketeo Said,

    @Veri:
    Thanks for pointing this out. I have fixed the link. It’s working now.

  18. Goliad Said,

    This helps understand how NotificationCenter works. Is a way to use an event inside First Tab to automatically switch to Second Tab without clicking Second Tab?

  19. miketeo Said,

    @Goliad: Check out UITabBarController’s selectedIndex property. It allows you change the tab bar’s current selected view controller. So you can change this property in your first tab’s event handler to switch to another tab.

  20. goliad Said,

    I want to jump to SecondTabView from OnOffTableCell, that is, whenever switchToggled (inside FirstTabView). I added the following code but could not get it to work.

    OnOffTableCell.h ————————————–

    @interface OnOffTableCell : UITableViewCell {

    IBOutlet UITabBarController *tabBarController;

    }
    @property (nonatomic, retain) UITabBarController *tabBarController;

    OnOffTableCell.m ————————–
    @synthesize tabBarController;

    – (void)switchToggled:(UISwitch*)control {
    NSLog(@”OnOffTableCell:switchToggled: ….
    [[NSNotificationCenter defaultCenter] …..
    tabBarController.selectedIndex=1;
    ….
    }

    I must miss something (very new to Xcode). Could you suggest a few options to debug? Thanks.

  21. miketeo Said,

    @goliad:
    I have uploaded a working example on this. You can download it at http://miketeo.net/wp/wp-content/uploads/2008/08/tabbartest.zip

  22. Goliad Said,

    That’s a really good example to show how tabBarController.selectedIndex to work. Thanks. I try to follow your example and add a button on SecondView so that I can jump back to FirstView without using its tab bar. So, I created a SecondViewController.h/m exactly as you did for FirstViewController. But when I hit
    “changeToFirstView” button, the app threw an error, complaining the method

    – (void)changeToFirstView:(id)sender {
    tabBarController.selectedIndex = 0;
    NSLog(@”changed to FirstView\n”);
    }

    Maybe I need to do something different than just copying the code for FirstViewController.

  23. miketeo Said,

    @Goliad:
    It is likely that your tabBarController attribute is not initialized and point to the UITabBarController instance. You can link the attribute and the UITabBarController object in the Interface Buider (IB). Please refer to the second “window” in the screenshot.

  24. Goliad Said,

    That was it! Thanks for the screenshot – it helps so much for those who are new to IB.

    With a good learning from this thread, I want to see if I can combine this UITabBar example with Notification method used in the UISlide example mentioned in this thread. For example, when UISlide is pull to to a predermined point (say value=50), it would switch to Second Tab automatically.

  25. Mike Said,

    This was a really great tutorial – probably the best I’ve read so far. Thank you so much for taking the time to make it. Coming from a similar background as you (.NET for 5 years), I have found the Cocoa framework and XCode to be incredibly frustrating, and moving from C# to Objective-C has seemed like such a step backwards. Your tutorial has illuminated many things for me. Once again, thanks!

  26. Tutorial for iPhone programming « JongAm's blog Said,

    […] http://miketeo.net/wp/index.php/2008/08/31/simple-iphone-tutorial-part-2.html; http://miketeo.net/wp/index.php/2008/08/31/simple-iphone-tutorial-part-3.html. […]

Add A Comment