Tuesday, September 25, 2012

Tabbed Application FROM Another ViewController


WHAT IF… you wanted the very first View to be an ordinary ViewController, then when you tap a button from the first View, the secondView uses a TabBarController, how do we do it? 

This is somehow related to the things we did from our previous tutorials:
http://iosmadesimple.blogspot.com/2012/09/tabbed-application-doing-it.html OR
http://iosmadesimple.blogspot.com/2012/09/tabbed-application-using-interface.html

//I'm using the latest Xcode as of this date, Xcode 4.5, you might find the views in my xib file a bit bigger in size than the usual ones.

1. I created a New Project, having "ViewController" class as my First View. Add a label and a button for this view. And it currently looks like this:

2. Create New Files, name it FirstTabViewController and SecondTabViewController, subclass of UIViewController. Add labels so as to indicate which tabVC is which.
First Tab ViewController UI

Second Tab ViewController UI

Doing it Programmatically

3. In ViewController Class, #import FirstTabVC and SecondTabVC, create a TabBarController property, synthesize it and make an IBAction method for our button.

4. Under viewDidLoad function of ViewController Class, allocate and initialize FirstTabVC and SecondTabVC and the tabBarController;

- (void)viewDidLoad {
    [super viewDidLoad];

    FirstTabViewController *firstTab = [[FirstTabViewController alloc] init];
    SecondTabViewController *secondTab = [[SecondTabViewController allocinit];
    
    firstTab.title = @"First Tab VC"; //TabTitle
    secondTab.title = @"Second Tab VC"; //TabTitle
    
    tabController = [[UITabBarController  allocinit];
    tabController.viewControllers = [[NSArray  alloc] initWithObjects:firstTab, secondTab, nil];
}

5. Add a code in IBAction that tells it that we should show the tabbed Controller. And remember to connect this IBAction to your button in your xib file.
-(IBAction)goToTabbedView:(id)sender {
    [tabController setSelectedIndex:0];
    //[self presentModalViewController:tabController animated:YES]; //deprecated in iOS 6.0; you may use this in older versions
    [self presentViewController: tabController animated:YES completion:NULL]; //you may put completion block here if there's anything you would like it to do after this task is successful
}


6. Hit Run! 

Doint it Using Interface Builder


1. Remove or comment out all your codes (the one we created above; step 4) in viewDidLoad in ViewController Class.

2. Drag a TabBarController from the Objects Library to the Placeholder/Objects Panel.
(Photo from previous posts.)

3. Add "IBOutlet" to your UITabBarController property and synthesize it; connect whatever outlets need to be connected.

4. Expand the Placeholder/Objects Panel, and the navigationController in ViewController.xib file.
(Photo from previous posts.)

5. Click the View Controllers under UITabBarController object, change their classes to FirstTabViewController and SecondTabViewController respectively.


How to go back from our very first View Controller?

1. Add a button to any of your Tab Controllers (FirstTabViewController or SecondTabViewController). Create an IBAction and connect it to the button you added.


-(IBAction)goToFirstView:(id)sender {
    [self.tabController dismissViewControllerAnimated:YES completion:NULL];
}


Hit Run!







Download Sample Project Here!

Saturday, September 22, 2012

Tabbed Application, Using Interface Builder


If you want to create a Tabbed Application programmatically, refer to this tutorial:
http://iosmadesimple.blogspot.com/2012/09/tabbed-application-doing-it.html

Let's create a Tabbed application using Interface Builder! :D

1. Create a new empty application. Make your own MainWindow.xib file, you already know how to do this. (If not, refer to this tutorial: http://iosmadesimple.blogspot.com/2012/08/creating-our-own-mainwindowxib-for.html)

2. Go to AppDelegate.h, add a UITabBarControllerDelegate
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>

3. add a UITabBarController property.
@property (strong, nonatomic) UITabBarController *tabBarController;

4. Synthesize your tabBarController variable in AppDelegate.m.

5. Create at least 2 View Controllers, name it First and Second ViewController. Add UILabels and other stuff, to indicate that such UI belongs to either of the two ViewControllers.

6. Add "IBOutlet" to UIWindow and UITabBarController properties in AppDelegate.h
@property (strongnonatomicIBOutlet UIWindow *window;
@property (strongnonatomic IBOutlet UITabBarController *tabController;

7. Go to your MainWindow.xib, Search for Tab Bar Controller from Objects Library and drag it to Placeholder/Objects Panel. Make the necessary connections from your AppDelegate Object outlets to your objects UIWindow and UITabBarController.

8. Right-click Window object in your Interface Builder, connect the "rootViewController" outlet to UITabBarController object.



9. Go to AppDelegate.m, under application:didFinishLaunchingWithOptions function, comment out all the codes inside that function, but leave these codes behind:
[self.window makeKeyAndVisible];
return YES;

10. Hit Run!

Let's set our two view controllers that we created a while a go, the First and Second View Controller.

11. Import the First and Second VC to your AppDelegate class.

12. Expand the Placeholders/Objects Panel, and the  TabController.

13. Select one of the two view controllers inside the Tab Controller, and change its class to "FirstViewController."

Do the same thing with the other view controller, set its class to "SecondViewController."

Hit Run and you're done! 




Note

You may add an image or a tabTitle for every ViewController by following these steps:

Expand the Placeholder/Objects Panel, the TabBarController object, and the ViewControllers under it. Click the "Tab Bar Item." Go to Attributes Inspector, the fourth button, next to "Identity Inspector." Change the Title or the Image under the "Bar Item" Category.

For the images, you have to import those images to your project first. Right-click the folders on the Project Navigator, choose "Add Files to project_name," choose the images you want to import.




Monday, September 17, 2012

UIPickerView Tutorial


1. Add a New File, subclass of ViewController, to your project. In my example, the name of my class is ViewController.

2. Open ViewController.xib and drag a pickerview to your xib file.



 3. Add a UIPickerView IBOutlet to your ViewController.h file, and synthesize it to your ViewController.m.
@property (nonatomic, strong) IBOutlet UIPickerView *myPickerView; //.h
@synthesize myPickerView; //.m

4. Connect your IBOutlet property to the object in your .xib file.


5. Go back to your ViewController.h, and make your interface header look like this:
@interface ViewController : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate

6. On your viewDidLoad, set the delegate and datasource of your pickerview to self;
- (void)viewDidLoad
{
    [super viewDidLoad];
    myPickerView.delegate = self;
    myPickerView.dataSource = self;
}

7. Add an array that will hold your items for you.
If your items are constant, use NSArray, else, use NSMutableArray.
@property (nonatomicstrong) NSArray *itemsArray; //.h
@ synthesize itemsArray; //.m

8. Initialize your array.
itemsArray = [[NSArray alloc] initWithObjects:@"Item 1", @"Item 2", @"Item 3", @"Item 4", @"Item 6", nil];

9. Add these delegate and datasource methods of pickerview in your ViewController.m class:
#pragma mark - UIPickerView DataSource
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 1;
}

// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return [itemsArray count];
}

#pragma mark - UIPickerView Delegate
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
    return 30.0;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return [itemsArray objectAtIndex:row];
}

//If the user chooses from the pickerview, it calls this function;
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    //Let's print in the console what the user had chosen;
    NSLog(@"Chosen item: %@", [itemsArray objectAtIndex:row]);
}

10. Done! Hit Run!





Wednesday, September 12, 2012

Tabbed Application, Doing it Programmatically


How to create a Tabbed Application without choosing Tabbed Application in creating a new project.

1. Create a new empty application. Make your own MainWindow.xib file, you already know how to do this.

2. Go to AppDelegate.h, add a UITabBarControllerDelegate
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>

3. Add a UITabBarController property.
@property (strong, nonatomic) UITabBarController *tabBarController;

4. Synthesize your tabBarController variable in AppDelegate.m.

5. Under function application:didFinishLaunchingWithOptions, let's allocate and initialize our tabBarController.
self.tabBarController = [[UITabBarController alloc] init];

6. Create a New File, Subclass ViewController, put all the UI components you want, you may do it programmatically, or using Interface Builder. 
In my example, I created FirstViewController and SecondViewController. I only put a UILabel in each ViewController, so that I will know that the shown ViewController is from first or second ViewController. Import these ViewControllers in your AppDelegate Class.

7. Allocate and Initialize your viewControllers, this is still under application:didFinishLaunchingWithOptions function:
 UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
    UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];

8. Set the view controllers of our tabBarController. 
self.tabBarController.viewControllers = [NSArray arrayWithObjects: viewController1viewController2nil];


Note: If you put more viewController objects in self.tabBarController.viewControllers array, tabBarController will automatically create more tabs for you. But it will limit up to five tabs only. 
If you have more ViewControllers to show, the tabBarController will automatically change the fifth tab to "More…". And when you click "More" tab, you will see a navigation-based view, and it places your other viewControllers in a table format. Upon selecting a row from the table, that's the time your viewController will be "pushed" and viewed.


9. Set the rootViewController of your window to tabBarController.
self.window.rootViewController = self.tabBarController;

10. Tab indices start at 0, tabBarController will automatically show the viewController on index 0 (of your array). But, you may choose to show a different ViewController first by:
[self.tabBarController setSelectedIndex:1];


Note

You may add an image or a tabTitle for every ViewController...

If you want to change the image or tabTitle of the firstViewController, go to FirstViewController.m, under the initialization function. add these codes.
self.title = @"First";
self.tabBarItem.image = [UIImage imageNamed:@"myImage1"]; //Example: the filename of your image is "myImage1.png"

For the images, you have to import those images to your project first. Right-click the folders on the Project Navigator, choose "Add Files to project_name," choose the images you want to import.




Sunday, September 9, 2012

Navigation Controller FROM Another View Controller

Or you may say "Navigation Controller as the second View," or "Navigation Controller's previous view is a ViewController." The purpose of this post is that the NavController is shown after a normal VC or any other views.

Our previous posts about Navigation Controllers only tackle about making it as our very first view. Now, what if you don't want your Navigation Controller as your first view? What if you want your first view to be a View Controller?

1. Create a New Project.

  • If you choose an Empty Application, create a New File, View Controller subclass, connect it to your AppDelegate using xib (MainWindow) or code it in application:didFinishLaunching method in AppDelegate.m
  • Or, you may choose Single View Application, a View Controller class is provided for you, and the View Controller Class is already connected to your AppDelegate Class (this is hasle free).

2. Add a label to your first ViewController (VC), and a button.
When we click the button, it must show a new view with navigation bar.

3. Create another ViewController subclass, name it "SecondViewController," add a label to your second VC just to indicate that the view belongs to the secondVC.

4. Go back to your first VC interface file, import your SecondVC. Add a UINavigationController property and synthesize it in your implementation file.

//.h file
@property (nonatomic, retain) IBOutlet UINavigationController *navController;

//.m file
@synthesize navController;



5. Go to your firstVC's .xib file, drag a Navigation Controller object from the Object's Library to your Placeholder/Object's panel (or you may simply double-click the Navigation Controller object from the Object's Library).

6. Connect your outlet to your NavigationController object.

7. Expand the Placeholders/Objects Panel by clicking the button inside the orange circle, expand the ViewController inside the Navigation Controller object. Change the class of that ViewController with the name of the class we create a while ago. In our case, it was the SecondViewController.

8. After changing the class, you must see that the ViewController is changed to "Second View Controller." This tells us that the SecondVC is the rootViewController of our NavigationController. When the NavigationController is shown, the UI of the SecondVC must be the view inside the NavigationController.

9. Go to your first VC's implementation file. Add an IBAction method to your button and let's add a code that will show the NavigationController with the SecondVC's view in it.

- (IBAction)goToNavigationController:(id)sender {
    [self presentModalViewController:self.navController animated:YES];
}
//Remember to connect your IBAction to your button in your .xib file.

10. And you're done! Hit Run!


Monday, September 3, 2012

Introduction to Objective-C

Refer to the first part of the tutorial from this link: http://iosmadesimple.blogspot.com/2012/07/introduction-to-xcode.html

Objectives:

  • To understand the class structure and its implementation in Objective-C
  • To get acquainted with Objective-C syntax
Objective-C uses Model-View-Controller design pattern. If you want to know more about MVC design pattern in Objective-C, refer to this link from Cocoa Lab. http://www.cocoalab.com/?q=node/24

Class Structure

  1. Interface Section - where your data components and function headers are located; found in .h files
  2. Implementation Section - where your implementation for your functions are located; found in .m files
  3. Program Section - these are your codes; where your instatiate objects to carry out your tasks

Class Definition and Instatiation Syntax

Interface (.h files)

@interface NameOfClass:ParentClass {
//instance variables
returnType nameOfVariable;
}

//instance methods
- (returnType)methodName1; //No Parameters
- (returnType)methodName2:(returnType)parameter; //With One Parameter
- (returnType)methodName3:(returnType)parameter1 ThisIsPartOfTheMethodNameWithData:(returnType)parameter2; //With MultipleParameters
@end

Implementation (.m files)

@implementation NameOfClass
- (returnType)methodName1 {
//Put your codes here
}

- (returnType)methodName2:(returnType)parameter {
//Put your codes here
}

- (returnType)methodName3:(returnType)parameter1 ThisIsPartOfTheMethodNameWithData:(returnType)parameter2 {
//Put your codes here
}
@end

Program

main.m file //Remeber to import the class you created
int main(int argc, char *argv[]) {
//Create instance of the class
NameOfClass *instanceName1 = [[NameOfClass alloc] init];

//Or you may do it this way
NameOfClass *instanceName2;
instanceName2 = [NameOfClass alloc];
instanceName2 = [NameOfClass init];

//Calling a class function
[instanceName2 methodName];
[instanceName2 methodName2:100]; //assume that the dataType of the parameter is int, let's pass integer 100

//If you no longer need the objects, release their memory
[instanceName1 release];
[instanceName2 release];
}



Navigation-Based Project, Using Interface Builder

If you have decided to make Navigation-Based Projects through coding, refer to this tutorial: http://iosmadesimple.blogspot.com/2012/08/navigation-based-project-doing-it.html

Create an Empty Application Project.


1. Make MainWindow.xib file, make all the necessary steps and connections --> you already know how to do that! 
If not, refer to this tutorial: http://iosmadesimple.blogspot.com/2012/08/creating-our-own-mainwindowxib-for.html

2. In our AppDelegate.h, add "IBOutlet" to our UIWindow property.
@property (strong, nonatomic)IBOutlet UIWindow *window;

3. Comment out the codes in AppDelegate.m, application:didFinishLaunchingWithOptions: function
    //self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    //self.window.backgroundColor = [UIColor whiteColor];


4. Go to MainWindow.xib, check the connections between your File's Owner, Object and Window.
 

5. Drag Navigation Controller from Objects Library, put it in the Placeholder/Object Panel with the File's Owner, Object, and UIWindow. 
6. Add a UINavigationController object in AppDelegate.h and connect navController variable to our NavigationController object in .xib


7. Right-click Window object in .xib, you'll see a "rootViewController" outlet. Connect it to the navigationController object. //this action corresponds to this line of code self.window.rootViewController = navController_; 


8. Expand the "Placeholder/Objects Panel" in Interface Builder.
9. Click the Navigation Controller Button on the left side. You should see objects like Navigation Bar, UIViewController, and under UIViewController, Navigation Item.



Let's create our first view!


Make a new file, subclass of UIViewController, let's name it FirstViewController. Play around with its xib file, add some labels and buttons. I added a label and a button to FirstVC's xib file.

10. Select UIViewController, change its class to "FirstViewController." You know where the Identity Inspector is! //Don't forget to import FirstViewController Class!




11. Hit Run!

Let's create a new ViewController Class, name it SecondViewController. Put some labels and buttons for its UI.

1. In FirstViewController.m, let's add an IBAction function. We can show the SecondViewController by:
-(IBAction)goToSecondVC:(id)sender {
    SecondViewController *secondVC = [[SecondViewController alloc] init];
    [self.navigationController pushViewController:secondVC animated:YES];
}
Make sure you imported the SecondViewController class in FirstViewController.
2. Connect the IBAction to your UIButton in InterfaceBuilder. TouchUpInside.
3. Done! Hit run!

When you click the button in the SampleViewController, you should be navigated to the SecondViewController.
/*Optional*/
If you want to add a Navigation Title to your SecondView, put this in SecondVC's viewDidLoad function. 
self.title = @"Second VC";

4. Without adding a code for a back button, UINavigationController automatically makes it for you. As you can see in your SecondViewController, there's a backbutton titled "Root View Controller"  <-- the Navigation Title of the previously showed ViewController.


UINavigationController keeps track of the ViewControllers opened by the user. It's a STACK of ViewControllers. The very firstVC or the rootVC is the first one in the stack, when you click the button to go to the next VC, it will push the second VC to the stack. And when you tap the "back button," it pops the second VC, thus, showing the previous VC.


Blocks From one Class to Another

One popular scenario in using blocks is when you need to update your view after a web service call is finished.