Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

James Goodin
James Goodin
2,483 Points

Success with Extra Credit project (Ben Jakuben course)

I did the Extra Credit following the first series of Ben Jakuben's self-distructing messaging app.

The requirement was...

Extra Credit Tabs Sans Storyboard

We didn't do much with code in this stage. We configured our tabs using a storyboard, but it's possible (and sometimes necessary) to create and configure a UITabBarController dynamically in code.

Create a simple app that has one view controller (it can be blank). In its viewDidLoad method, add a UITabBarController, and then add 5 tabs programmatically, labeled "1", "2", etc.

Dynamic Tabs

Add a new root view controller and embed it in a navigation controller. In this new view controller, add a text field and a button. Have the user enter a number (1-5) in the text field (prevent any other values!), and when the button is tapped, present the view controller from the Extra Credit above. Use the number entered by the user to determine how many tabs to create.

My Notes/code: This was from a combination of some understanding of the tab bar to googling for help to trial/error which I'm trying to improve on by being here. Here are my main code sections for your perusal if of interest. It's appDelegate didFinishLaunchingWithOptions method where I initially was trying to do all, then I figured out how to disable Storyboard (info.plist) integration which might not have been necessary and did my main code in the MainViewController.m. Learned a lot with this project.

from appDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor grayColor];

    MainViewController *viewController = [[MainViewController alloc] init];

    self.window.rootViewController = viewController;

    [self.window makeKeyAndVisible];
    return YES;
}

from MainViewController.m
//
//  MainViewController.m
//  TabBarMe
//
//  Created by Admin on 4/4/15.
//  Copyright (c) 2015 Wood and Wire Ware. All rights reserved.
//

#import "MainViewController.h"

@interface MainViewController ()
@property (nonatomic, strong) UITextField *textField;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UILabel *credit;
@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0f, 120.0f, 340.0f, 30.0f)];
    self.titleLabel.text = @"Extra Credit: Dynamic Tabs sans Storyboard";
    self.titleLabel.textColor = [UIColor whiteColor];
    [self.view addSubview:self.titleLabel];

    self.label = [[UILabel alloc] initWithFrame:CGRectMake(40.0f, 150.0f, 320.0f, 30.0f)];
    self.label.text = @"Please enter number of tabs to display";
    [self.view addSubview:self.label];

    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(140.0f, 180.0f, 100.0f, 30.0f)];
    self.textField.delegate = self;
    self.textField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:self.textField];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(120.0f, 230.0f, 150.0f, 30.0f);
    [button addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Tap to Display Tabs" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [self.view addSubview:button];

    self.credit = [[UILabel alloc] initWithFrame:CGRectMake(120.0f, 600.0f, 140.0f, 30.0f)];
    self.credit.text = @"Jim Goodin, 2015";
    self.credit.textColor = [UIColor blackColor];
    [self.view addSubview:self.credit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    // may not be necessary but implemented
    [textField resignFirstResponder];
    return NO;
}

- (void)buttonPressed {
   // launches TabBar view(s) 
   [self createTabBar];
}

- (void)buttonPressed2 {
    // return to home view viewController
    [self.tbc dismissViewControllerAnimated:self.tbc completion:nil];
}

- (void)createTabBar {
    // create and load tabbar with number of tabs created
    // based on user input
    NSInteger a;

    self.tbc = [[UITabBarController alloc] init];
    UIViewController *firstVC = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    firstVC.view.backgroundColor = [UIColor blueColor];
    UIViewController *secondVC = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    secondVC.view.backgroundColor = [UIColor redColor];
    UIViewController *thirdVC = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    thirdVC.view.backgroundColor = [UIColor greenColor];
    UIViewController *fourthVC = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    fourthVC.view.backgroundColor = [UIColor orangeColor];
    UIViewController *fifthVC = [[UIViewController alloc] initWithNibName:nil bundle:nil];
    fifthVC.view.backgroundColor = [UIColor darkGrayColor];

    firstVC.tabBarItem.title = @"1";
    secondVC.tabBarItem.title = @"2";
    thirdVC.tabBarItem.title = @"3";
    fourthVC.tabBarItem.title = @"4";
    fifthVC.tabBarItem.title = @"5";

    [self evaluateTabBar:a];
    a = [self.textField.text integerValue];
    if (a == 1) {
        NSArray *array = [[NSArray alloc] initWithObjects:firstVC, nil];
        self.tbc.viewControllers = array;
        [self addButtonToEachView];
    }
    if (a == 2) {
        NSArray *array = [[NSArray alloc] initWithObjects:firstVC, secondVC, nil];
        self.tbc.viewControllers = array;
        [self.view addSubview:self.tbc.view];
        [self addButtonToEachView];
    }
    if (a == 3) {
        NSArray *array = [[NSArray alloc] initWithObjects:firstVC, secondVC, thirdVC, nil];
        self.tbc.viewControllers = array;
        [self.view addSubview:self.tbc.view];
        [self addButtonToEachView];
    }
    if (a == 4) {
        NSArray *array = [[NSArray alloc] initWithObjects:firstVC, secondVC, thirdVC, fourthVC, nil];
        self.tbc.viewControllers = array;
        [self.view addSubview:self.tbc.view];
        [self addButtonToEachView];
    }
    if (a == 5) {
        NSArray *array = [[NSArray alloc] initWithObjects:firstVC, secondVC, thirdVC, fourthVC, fifthVC, nil];
        self.tbc.viewControllers = array;
        [self.view addSubview:self.tbc.view];
        [self addButtonToEachView];
    }
}

- (NSInteger)evaluateTabBar:(NSInteger)answer {
    // user responds to prompt for how many tabs he wants on the bar
    return answer;
}

- (void)addButtonToEachView {
    [self presentViewController:self.tbc animated:YES completion:nil];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(120.0f, 200.0f, 130.0f, 30.0f);
    [button addTarget:self action:@selector(buttonPressed2) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"Unload TabBar" forState:UIControlStateNormal];
    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [self.tbc.view addSubview:button];
}
@end
Brendan Bond
Brendan Bond
2,682 Points

Great job! Did you originally try to create the UITabBarController in the root view controller's viewDidLoadMethod? It was throwing an exception for me every time I would select a tab. I changed the UITabBarController to be a property of the view controller (as it looks like you did), but I'm really curious as to why you can't just create the tab controller when its superview loads.

James Goodin
James Goodin
2,483 Points

Brendan thanks. Honestly I think I tried everywhere if you will. I have done a tabBar before (Treehouse) programmatically and in the appdelegate 'didFinishLoading...' and experimented initially with that but it was cart before horse. I knew where the app was going re the initial input from the user would control the outcome so it was making sense it had to be spawned from a method in the main view at start. This one was a good challenge and it was cool to get it to work as you experienced. Kudos and thanks for commenting on my attempt. See ya round the 'treehouse'

JIHOON JUNG
JIHOON JUNG
10,927 Points

Wow, hope to take a video with the project and share how you've done with self-learners here :D

have one question, though. How did you get "self.tbc"? it seems tbc is not defined above.