Sunday, November 23, 2014

iOS Tutorial - Part 25 - Xcode - debugging - tools

Xcode debugging tools


Video Description 
Sometimes when you run the app and do some actions, application stops and it goes to a class name "main.m". This is happen when an exception raises that is not handled. In order to get more information about the crash and the exception we have different tools. In the following we will get familiar with some of these tools.

Console:

When exception raises or app crashes, at the bottom of the Xcode, you can see console that has some useful information. It can tells what kind of exception happened and what method causes this problem.

All Exception Breakpoint:

From console we can see the method name that causes the error but it's very inefficient to search all over the code to find the method. In order to find the line of code that causes the crash we need to add "All Exception Breakpoint". Open Breakpoint navigator tab on the top left side of Xcode. At the very bottom of the page click on "+" button. Select "Add Exception Breakpoint". Now if you run the program and it crashes, it brings up the line of code that causes the crash.

Custom Breakpoint

You can add custom breakpoint anywhere in your app. It stops the app and shows the line of code you add the breakpoint. In order to add custom breakpoint, just click on the left side border of the line you want. Blue arrow will show up. If you run the application and it reaches the breakpoint you have multiple buttons that you can use to get more detail information. These buttons are as follow:


Continue:

It will continue running the application (Executing rest of the code).

Step Over:

It will go one step ahead, for example if there is a line after your breakpoint it will go to the next line.

Step into:

It will go deep inside of that line of code. For example if you call other methods in this line if you step into, it will go to that method. If you have property in that line it will show setter and getter. If there is nothing to go in, it will go to the next line.

Step out:

If you step into via the "Step into" button, you can go out by pressing "Step out".

Conditional Breakpoint:

If you add a breakpoint, whenever app reaches that line of code, it will pause and show the line you specified. If you want to pause only in certain condition, just right click on the breakpoint and from the opening menu select "Edit Breakpoint". From the opening window add your condition in the blank field. Your condition should be written in objective c language.

Debug View Hierarchy:

If you want to have a 3D view of your application, run the application then press "Debug View Hierarchy"

Sunday, November 16, 2014

iOS Tutorial - Part 24 - UIScrollView

UIScrollView


Video Description 
When the contents of a view is not fit inside of the device size we need to use scroll view. We can easily drag and drop it inside of our view controller. Then setting the content size of the scroll view with setContentSize method.

contentSize

If you are setting the content size of the scroll view equal to a view element, make sure that the view element size is set by that time. For example for imageView, we should set the scroll view size after imageView gets its image, like bellow.
    UIImage *img = [[UIImage alloc] initWithData:dataImage];
    [self.imageView setImage:img];
    self.scrollView.contentSize = self.imageView.image.size;

minimumZoomScale and maximumZoomScale

In order to add zooming feature to the scrollView we need to set the min and max zoom scale. minimumZoomScale indicates the least scale that user can zoom out (0 to 1). maximumZoomScale indicates maximum scale that user can zoom in to the picture.
   self.scrollView.minimumZoomScale = 0.2;
   self.scrollView.maximumZoomScale = 3.0;
A good place for setting these properties are in the scrollView setter, like bellow:
- (void)setScrollView:(UIScrollView *)scrollView
{
    _scrollView = scrollView;
    _scrollView.minimumZoomScale = 0.2;
    _scrollView.maximumZoomScale = 3.0;
}
If you run the program it will not work because we have to define "Which view we want to zoom in scrollView". We indicate this view by implementing one of UIScrollViewDelegate method (viewForZoomingInScrollView). Before implementing this delegate method don't forget to add the name of the delegate method in front of interface like <UIScrollViewDelegate> and setting delegate equal to self. We can add it in scrollView setter like bellow:
- (void)setScrollView:(UIScrollView *)scrollView
{
    _scrollView = scrollView;
    _scrollView.minimumZoomScale = 0.2;
    _scrollView.maximumZoomScale = 3.0;
    _scrollView.delegate = self;
}

viewForZoomingInScrollView

Inside of this delegate method we just return the view that we want to be able to zoom. In our example it's imageView, so the implementation would look like:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

zoomScale

In order to set the scale of zoom programmatically we can use this property. For example if we want to have the zoom scale of 1 (Actual size) we have:
self.scrollView.zoomScale = 1.0;

flashScrollIndicators

We don't have scroll bars on the screen all the times. We can show them for a moment. In order to flash the scroll bars for the user you can use flashScrollIndicators method like bellow:
[self.scrollView flashScrollIndicators];

Download

Download this App from here

Sunday, November 2, 2014

iOS Tutorial - Part 23 - UIAlertController, UIImagePickerController

UIAlertController, UIImagePickerController


Video Description 

UIAlertController

Displays an alert message to the user. This class replaces the UIActionSheet and UIAlertView classes for displaying alerts.

Steps to create UIAlertController

1- Initialize allertController with the specified title, message and the style you want.
    UIAlertController *alertCtrl = [UIAlertController alertControllerWithTitle:@"Alert Title" message:@"Alert Message" preferredStyle:UIAlertControllerStyleActionSheet];
2- Create actionAllert with specified title, style and handle the event when user taps on it
    UIAlertAction *buttonOnAlertCtrl = [UIAlertAction actionWithTitle:@"Button Title" style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action)
                                                    {
                                                        //Handle Event
                                                    }];
3- Add the button to the allertController
[alertCtrl addAction:buttonOnAlertCtrl];
4- Show it to the screen
[self presentViewController:self.alertCtrl animated:YES completion:nil];

UIImagePickerController

You can use UIImagePickerController to get image from PhotoLibrary or Camera

Steps to get image from Camera

1- Create a property like bellow to access UIImagePickerController anywhere inside of your class @property (strong, nonatomic) UIImagePickerController *imagePicker; 2- Initialize and allocate memory
self.imagePicker = [[UIImagePickerController alloc] init];
//Set delegate method equal to self
self.imagePicker.delegate = self;
//Set source type (Here we choose camera)
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
//Present the camera to the screen
[self presentViewController:self.imagePicker animated:YES completion:nil];
2- Add delegate names (UIImagePickerControllerDelegate, UINavigationControllerDelegate) in front of the interface
@interface ViewController () 
3- Implement UIImagePickerControllerDelegate method
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSData *dataImage = UIImageJPEGRepresentation([info objectForKey:@"UIImagePickerControllerOriginalImage"],1);
    UIImage *img = [[UIImage alloc] initWithData:dataImage];
    //img is the picture that user captured with the camera, you can do whatever you want with this picture
    //Add your own implementation here
}

Get get image from Photo Library

The steps are exactly like the steps for getting image from camera, except the source type. You should use the following line instead of line 4 of step 2:
    self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

Write Macro to compile different block of code for simulator vs. actual device

If we want to tell the compiler to run a block of code if its simulator and other block of code if it's on actual device, we can use the following if else statement: #if TARGET_IPHONE_SIMULATOR //Put the block of code that you want to be executed if it's running on the simulator #elif TARGET_OS_IPHONE //Put the block of code that you want to be executed if it's running on the actual device #endif

All of the code for this tutorial

#import "ViewController.h"

@interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) UIAlertController *alertCtrl;
@property (strong, nonatomic) UIImagePickerController *imagePicker;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setupAlertCtrl];
}

- (void) setupAlertCtrl
{
    self.alertCtrl = [UIAlertController alertControllerWithTitle:@"Select Image"
                                                         message:nil
                                                  preferredStyle:UIAlertControllerStyleActionSheet];
    //Create an action
    UIAlertAction *camera = [UIAlertAction actionWithTitle:@"Camera"
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action)
                                                    {
                                                        [self handleCamera];
                                                    }];
    UIAlertAction *imageGallery = [UIAlertAction actionWithTitle:@"Image Gallery"
                                                     style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction *action)
                                                    {
                                                        [self handleImageGallery];
                                                    }];
    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel"
                                                           style:UIAlertActionStyleCancel
                                                         handler:^(UIAlertAction *action)
                                   {
                                       [self dismissViewControllerAnimated:YES completion:nil];
                                   }];

    
    //Add action to alertCtrl
    [self.alertCtrl addAction:camera];
    [self.alertCtrl addAction:imageGallery];
    [self.alertCtrl addAction:cancel];
    
    
}

- (IBAction)selectImagePressed:(UIButton *)sender
{
    [self presentViewController:self.alertCtrl animated:YES completion:nil];
}

- (void)handleCamera
{
#if TARGET_IPHONE_SIMULATOR
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error"
                                                                   message:@"Camera is not available on simulator"
                                                            preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK"
                                                 style:UIAlertActionStyleDefault
                                               handler:^(UIAlertAction *action)
                                                {
                                                    [self dismissViewControllerAnimated:YES completion:nil];
                                                }];
    
    [alert addAction:ok];
    [self presentViewController:alert animated:YES completion:nil];
#elif TARGET_OS_IPHONE
    //Some code for iPhone
    self.imagePicker = [[UIImagePickerController alloc] init];
    self.imagePicker.delegate = self;
    self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    [self presentViewController:self.imagePicker animated:YES completion:nil];

#endif
}

- (void)handleImageGallery
{
    self.imagePicker = [[UIImagePickerController alloc] init];
    self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    self.imagePicker.delegate = self;
    [self presentViewController:self.imagePicker animated:YES completion:nil];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSData *dataImage = UIImageJPEGRepresentation([info objectForKey:@"UIImagePickerControllerOriginalImage"],1);
    UIImage *img = [[UIImage alloc] initWithData:dataImage];
    [self.imageView setImage:img];
    [self.imagePicker dismissViewControllerAnimated:YES completion:nil];
    
}

Download

Download this App from here

Monday, September 29, 2014

iOS Tutorial - Part 21 - Gestures

Gestures


Video Description 
If we want to recognize the user's touch events we have to use gesture recognizers. Events like pan, swipe, pinch ... are recognizable view UIGestureRecognizer class. We need to do the following steps for implementing Gestures.
1. Add the gesture recognizer to the view in order to recognize the gesture
2. Provide an implementation to handle the gesture
There are two approach in order to implement the above steps. First through the storyboard, second programatically. Lets start with the storyboard:

Add GestureRecognizer using Storyboard

1. From right bar side of Xcode in Object pallet, drag your desired gesture and drop it on the view that you want to implement the gesture.
2. Once you are done with the previous step, an icon will appear at the top of the view controller. If you go hover it, it will show the type of the gesture (e.g Swipe Gesture Recognizer). Control drag from this icon to your controller and make an IBAction. You can have your implementation inside of that method

Add GestureRecognizer programmatically

1. Create an outlet for the view that we want to have gesture for it, inside of it's controller. Control drag from your custom view to it's controller. If your view is created programmatically you don't need to create an outlet, just use the name of your view for next step.
2. Add the desired gesture recognizer to the outlet.
[self.yourCustomView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self.yourCustomView action:@selector(pan:)]]; 
3. Implement or handle the gesture inside of custom view class (not controller).

State property

Gesture recognizers have a property called "state" and it analyzes the current state of a touch. For example if user just started pan gesture, it's on the state "UIGestureRecognizerStateBegan". Another state is when the gesture is changing for example for pan, user dragging his finger on the screen and the position of his finger is changing. This state is called "UIGestureRecognizerStateChanged". When the gesture ends, the state will go to "UIGestureRecognizerStateEnded". The first two states are for the gestures that are continuous like pan and pinch. Gestures like tap and swipe doesn't have began and changed state, instead they have state called "UIGestureRecognizerStateRecognized". This state is for the time that device recognizes the gesture. If our gesture depends on the state of the gesture we can check by these properties.

Download

Download the Gesture App from here

Sunday, September 7, 2014

iOS Tutorial - Part 20 - Draw a Custom View

Draw a Custom View


Video Description 
Previously we drag and drop whatever view that we want from storyboard pallet and inset it inside of the view controller. But what if we want a custom view like a blue circle! In this case we need to draw the view by code. In order to draw we need to get familiar with some C struct types:

CGFloat: It's just a float type but we use it only for drawing
CGFloat myCGFloat = 12.6;
CGPoint: It represents a point in view. It has x (horizontal distance) and y (vertical distance). Both x and y are type CGFloat. We can make a CGPoint with the help of method CGPointMake(x, y)
CGPoint myCGPoint = CGPointMake(27.5, 16.7)
CGSize: It represents with and height of the view. Both width and height are type CGFloat. We can make a CGSize with the help of method CGSizeMake(width, height)
 
CGSize myCGSize = CGSizeMake(45.0, 35.5)
CGRect: We can specify a rectangle with the origin of CGPoint and size of CGSize. We can make a CGRect with the help of method CGRectMake(x, y, width, height)
CGRect myCGRect = CGRectMake(10.0, 20.0, 50.0, 45.5)

Coordinates: Origin of the view coordinate system is upper left corner of the device

Views have 3 properties related to their location:

bounds: Your view's internal drawing space's origin and size the bounds property is what you use inside your view's own implementation.
center: The center of your view in your superview's coordinate space
frame: A rectangle in your superview's coordinate space which entirely contains your views bounds.size

In the above picture here are the View B's properties:
bounds = ((0, 0), (200, 250));
frame = ((140, 65), (320, 320));
center = (300, 255)

Steps to draw something inside of the view

First of all drag and drop UIView from Object Library or pallet inside of view controller. Then Create a new file by clicking on file/new/File... . Put a name (e.g MyCustomView) for this file and set supperclass to UIView. Once you create this file, tap on this view (UIView) in storyboard and from right side menu select identity inspector tab. From class dropdown menu select the file name that you just created (e.g MyCustomView). Now open .m file (MyCustomView.m) and follow the steps.

1. Add the following method in .m file
- (void)drawRect:(CGRect)rect
{
   //Draw here
}
2. Use UIBezierPath to draw your custom path like an example bellow
UIBezierPath *trianglePath = [[UIBezierPath alloc] init];
3. Define your custom path like an example bellow
    [trianglePath moveToPoint:CGPointMake(25, 10)];
    [trianglePath addLineToPoint:CGPointMake(120, 140)];
    [trianglePath addLineToPoint:CGPointMake(7, 120)];
you can also close the path by the following command
[trianglePath closePath];
4. Set Stroke and Fill like bellow
    [[UIColor greenColor] setFill];
    [[UIColor redColor] setStroke];
    [trianglePath fill];
    [trianglePath stroke];

Some Useful UIBezierPath methods

UIBezierPath has a lot of useful methods that you can find in it's documentation but here are some of cool and important ones:
Rounded Rect: In order to draw a rounded rect we can use the following method
UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:12];
[roundedRect stroke];
Oval Rect:
UIBezierPath *ovalRect = [UIBezierPath bezierPathWithOvalInRect:self.bounds];
[ovalRect fill];
addClip: This would clip all drawing to be inside the roundedRect
[roundedRect addClip];

What if your bounds changes!

By default, there is no redraw when your bounds change. Instead the "bit" of your view will be stretched or moved. You can change this default behavior by using a property called contentMode. You can set it like bellow:
self.contentMode = UIViewContentModeRedraw;

Download

Download the Web App from here

Friday, August 22, 2014

iOS Tutorial - Part 19 - Create a Web Application, UIWebView

Create a Web Application, UIWebView


Video Description 
Web Application is an App that is written with HTML,CSS,JavaScript and has a wrapper to be able to show on a device. In this tutorial we will learn how to create a web app. In order to create a web application, follow the bellow steps:
1. create a new project
2. From storyboard, drag and drop WebView from pallet to the view controller
3. Control drag from web View to it's controller to create a property for the webView
4. Drag and drop your HTML files, inside of the project (Make sure you copy as a reference folder)
5. In ViewController inside of viewDidLoad add the following lines:
- (void)viewDidLoad
{
    [super viewDidLoad];
 self.webView.delegate = self;
    self.webView.scalesPageToFit = YES;
    
    NSString *htmlFile = [[NSBundle mainBundle] pathForResource:@"bootstrap" ofType:@"html"];
    NSURL *url = [NSURL fileURLWithPath:htmlFile];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0.0];
    
    [self.webView loadRequest:request];
}  
You are done. If you run the application it should show the HTML content.

Show a URL in the WebView

If you want to show a website, you need to change your request like bellow:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];

Add Back, Forward, Stop and Refresh button

You can easily add above buttons for your WebView without even writing any code for it. All you have to do is to add some buttons to the screen and from each individual button, control drag to the WebView. It shows a list containing reload, goBack, goForward, stopLoading. Based on your button click to any of these links and they will work.

Download

Download the Web App from here

Saturday, August 9, 2014

iOS Tutorial - Part 18 - Create Protocol, prepareForSegue

Create Protocol, prepareForSegue


Video Description 

prepareForSegue

When we connect two view controllers from storyboard, the following method will be called when first view wants to transmits to the second view.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    
}
Because this method is called before transition, so we can initialize or set some value for the next view controller. segue has two important property:

1)segue.identifier

In storyboard click on the arrow that links two view controllers then in attribute inspector tab on right side toolbar give the name in identifier field. Now in prepareForSegue we can check if the identifier matches the one that we are looking. The following is statement goes inside of prepareForSegue just to protect our application from any exception or crash.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"AddContact"])
    {
        //Do something
    }
}

2)segue.destinationViewController

As it can be guessed destinationViewController represents the next view controller. We can cast it to the next class name.

Casting in Objective-C

In order to force the compiler to consider a different type for an object we use casting. It's so simple to use. Yo just have to add a desired type inside of () and you are done. For example here we want segue.destionationViewController to have a type of AddContactVC. We should write:
(AddContactVC *)segue.destinationViewController
You may ask why we should cast!!! If we don't cast, compiler couldn't understand what is our specific type so it cannot see the available methods.

Create Protocol

If we have two different view controllers and we want them to talk back and forth, we need to define protocol and delegate. If you remember in textField delegate methods we used some built-in protocols and delegates. In this tutorial we will create our own protocol and delegate methods.

Steps to Create Protocol (Custom Delegate)

We have two view controllers in this example (Contact List) first view controller is a table view controller that shows the contact and the second view controller is the place that we add contact to the list. First view controller would be our delegate and second view controller would be our delegator. Here are the steps for delegator class:

1)Create Protocol

Add the following lines inside of the .h file of delegator class (AddContactVC) before @interface:
@class AddContactVC;
@protocol AddContactVCDelegate
- (IBAction)dismissAddContactVC:(AddContactVC *)sender;
- (void)addContactName:(NSString *)name phone:(NSString *)phone;
@end
@class is kind of our promise to compiler that we will define AddContactVC class in the following. If we don't put @class compiler will give error that there is not a class called AddContactVC. @protocol defines the name of the protocol and start point of it's methods. @end defines the end of the protocol.

2)Create Delegate Property

Create a weak property for our delegate between @interface and @end of delegator .h file.
@property (nonatomic, weak) id <AddContactVCDelegate> delegate;

3)Use delegate property in .m file

Inside of delegator .m file we should use our delegate property in appropriate place. In this example we have two delegate methods. The first method should be called when the user taps on the done button. And the second one should be used when the user taps on the add button. Open AddContactVC .m file control+drag the done button and add button to the implementation portion and create IBAction, then inside of these methods we can use our delegate property like bellow:
- (IBAction)dismissAddContactVC:(UIBarButtonItem *)sender
{
    [self.delegate dismissAddContactVC];
}

- (IBAction)addContactPressed:(UIButton *)sender
{
    [self.delegate addContactName:self.nameField.text phone:self.numberField.text];
}
Second method not only notifies us about user interaction but also sends two parameters, which are name and phone so we can use them to add to our table.
Here are the steps for delegate class:

4)Set delegate equal to self

First step to tell the compiler that we want to implement some delegate is to put our class delegate equal to self. Most of the time the best place is when we create an instance of delegator class but in this example since we have the instance, which is
(AddContactVC *)segue.destinationViewController
So we don't need to instantiate another instance we can use it and set the delegate equal to self like bellow:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"AddContact"]) {
        [ (AddContactVC *)segue.destinationViewController setDelegate:self];
    }
}

5)Add <delegateName> in front of @interface

The second step to tell the compiler that we want to implement some delegate methods is to declare the delegate name in fron of @interface of delegate class. Before doing that make sure you import the delegator class.
#import "AddContactVC.h"
@interface ContactTVC () <AddContactVCDelegate>

6)Implement the delegate methods

The last but not the least is implementing the delegate methods
- (void)dismissAddContactVC
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)addContactName:(NSString *)name phone:(NSString *)phone
{
    [self.names addObject:name];
    [self.phones addObject:phone];
    [self.tableView reloadData];
    [self dismissAddContactVC];
}
First method uses dismissViewControllerAnimated:YES completion:nil, which is one of view controller methods for dismissing the modal view. Second method adds the arguments to the array and then it reloads the table view by a method called reloadData. Then it calls our method dismissAddContactVC to dismiss the modal view once the user add new contact.

Rename files in Objective-C

In .m or .h file select the name of the file you want to change, then right click on it, from the opening drop down menu select Refactor/Rename. Then specify your new name and press preview. It will show you all the changes, you can confirm the changes by clicking on save button.

Download

Download the Contact List App with protocol from here

Wednesday, August 6, 2014

iOS Tutorial - Part 17 - Modal Segue, Connect View Controllers

Modal Segue, Connect View Controllers


Video Description 

Modal Segue

It's fairly easy to present a modal view triggering by a button. You just need to have two view controllers in the story board. Inside of the initial view you add a button and control drag from that button to the other view controller. It shows you a drop down menu when you realese the mouse. Select modal from the options and you are done.

Download

Download the Contact List App with modal from here

Friday, July 25, 2014

iOS Tutorial - Part 16 - UITableViewController - Hide Status Bar

UITableViewController, Hide Status Bar


Video Description 

UITableViewController

In order to show a table in your application you should use table view and it's controller. By default application adds a View Controller in the story board. We need to delete that and drag a Table View Controller into the story board. We also have to delete the ViewController.h and ViewController.m (Move to trash). Then we have to create a new file for our Table View Controller. Command + N or in File menu New/File..., Hit Next button and then give it a name like ContactTVC. Add subclass as: UITableViewController and hit Next button and then Create button.
If you open ContactTVC.m you will see some default methods. We need just the following methods
viewDidLoad
numberOfSectionsInTableView:
numberOfRowsInSection:
cellForRowAtIndexPath:
You can remove the rest of them or keep them as is.

#pragma mark -

The brown line of code that starts with #pragma is just for the convenience of developers to categorize their methods so they can find them easily. For example by specifying following three methods underneath #pragma mark - Table view data source
numberOfSectionsInTableView:
numberOfRowsInSection:
cellForRowAtIndexPath:

Table View Components

The following picture shows two sections with their components. From top level we have sections, then for each section we have header and footer.

numberOfSectionsInTableView

In this method you specify the number of sections that you want to have in your table. If you delete this method the default value is 1. Since we only have 1 section in our table we put number 1 as a return value.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

numberOfRowsInSection

In this method we specify the number of rows in each section. because we have only one section so we return only one value. We don't want to hard code this value, we want it to be dynamic. It should be equal to the number of items inside of our array. What is our array? Since it's a contact list application we need to have some names. We create a NSArray property and we put all of the names inside of this array like bellow.
@property (nonatomic, strong) NSArray *names;
We lazily allocate and initialize our array from it's setter by writing
- (NSArray *)names
{
    if(_names == nil)
    {
        _names = [[NSArray alloc] init];
    }
    return _names;
}
Then we add our names inside the array in viewDidLoad method (View life cycle).
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.names = [NSArray arrayWithObjects:@"Kasra", @"duboisvb", @"Brendanrooney", @"Magdalena", @"Shrikant", @"Subramanian", @"Revanth", @"Антон", @"Venkateswara",  @"Neil", @"Rajesh", @"CulquiproduccionesX3", @"李宗国", @"Ahmed", nil];
}
Now we can add our dynamic number of rows in each section with help of count method. It returns the number of items inside of the array.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.names.count;
}

cellForRowAtIndexPath

It's time to add our data inside of each cell. We uncomment the cellForRowAtIndexPath method and create a cell with reusable identifier. iOS reuses cells for showing table view so it needs and identifier. In order to define an identifier we need to go to the story board and select the cell. Then from Attribute Inspector add a name inside of identifier field, like "Cell". Then you come back to the ContactTVC.m and add the same identifier you defined in story board in front of dequeueReusableCellWithIdentifier:. Next we check if the cell is nil we allocate and initialize memory for it. Then we use "textLabel" and its property "text" to set the label of our cell.
We want each array items to be shown in different row. So we use one of the arguments of this method which is "indexPath" and it's property "row". It returns the number of the row that is being set. Finally we can use NSArray method for returning array object based on their index, which is objectAtIndex. At the end we return the cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    
    if( cell == nil)
    {
        cell = [[UITableViewCell alloc] init];
    }
    cell.textLabel.text = [self.names objectAtIndex:indexPath.row];
    return cell;
} 

Connect the view controller to it's class

If you run the app now, it would bot show anything because we have not connected the Table View Controller to the File that we created (ContactTVC). In order to connect it, go to the storyboard, select the view controller, then from identity inspector open the Class drop down menu and select the class that we created, which is ContactTVC. Now if you run the application it shows the names.

Hide Status Bar

If you notice, the status bar is over our names, so let's get rid of it. Under you project navigator open the "Supporting Files" group folder. Select .plist file. Click on the last item of this list. A plus button will be shown, click on the plus button and in the new row, type: "View controller-based status bar appearance". For the value of this row, select or write "NO". Again create another row and this time write: "Status bar is initially hidden" and for value type "YES". Now if you run the application, status bar is gone.

Add subtitle for Cell

In order to have phones under each name, we should follow the same pattern and create an array then add all phones. But this time instead of textLabel we use detailTextLabel.
cell.detailTextLabel.text = [self.phones objectAtIndex:indexPath.row];
If run the application it would not show the subtitles because we have not specified the style of the cell. We can do it either programmatically or in story board. In story board click on the Cell and from Attribute Inspector open style drop down menu. You can choose your style here. For this application we choose Subtitle. Now if you run the application it would show the numbers under each name.

Add Image to the cell

In order to have an image for each cell, we can follow the same pattern but since I have only one picture for all cells its much easier because I don't need array anymore. I just have to set the property called cell.imageView.image. First we have to drag and drop our image inside of xcode. There is a folder called Images.xcassets, click on this folder and drag your image (If it's .png) under launchImage. 1x is for regular display and 2x is for retina display. If you have better resolution of this image with larger size you can drop it in 2x place holder. Now all you need to do is to call the UIImage method to grab the image and then set it for each cell.
cell.imageView.image = [UIImage imageNamed:@"Rose"];
"Rose" Is the name of the image file that you added to the Xcode.

Static table view, Header & Footer

All of above settings were for Dynamic contents. We have Static content, which is very easy to set. You can set it inside of the story board. Static content means that the number of the rows and sections are fixed and static. Since it's fixed we can change their labels right from the story board. In order to change the content mode from dynamic to static, open story board, click in the middle of the Table View Controller, where it has a text "Table View Prototype Content", then open Attribute inspector. From Content drop down menu you can select static. By default it has 3 rows but you can set as many as you want by opening "Editor / Show Document Outline" In Xcode menu bar. Then under Table View, tap on Table View Section and open Attribute Inspector. You can set the number of rows and also Header and Footer of the section.

All of the code for this tutorial

ContactTVC.m
#import "ContactTVC.h"

@interface ContactTVC ()
@property (nonatomic, strong) NSArray *names;
@property (nonatomic, strong) NSArray *phones;
@end

@implementation ContactTVC

- (NSArray *)names
{
    if(_names == nil)
    {
        _names = [[NSArray alloc] init];
    }
    return _names;
}

- (NSArray *)phones
{
    if(_phones == nil)
    {
        _phones = [[NSArray alloc] init];
    }
    return _phones;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.names = [NSArray arrayWithObjects:@"Kasra", @"duboisvb", @"Brendanrooney", @"Magdalena", @"Shrikant", @"Subramanian", @"Revanth", @"Антон", @"Venkateswara",  @"Neil", @"Rajesh", @"CulquiproduccionesX3", @"李宗国", @"Ahmed", nil];
    
    self.phones = [NSArray arrayWithObjects:@"111-111-1111", @"222-222-2222", @"333-333-3333", @"444-444-4444", @"555-555-5555", @"666-666-6666", @"777-777-7777", @"888-888-8888", @"999-999-9999", @"101-010-1010", @"111-111-1111", @"121-212-1212", @"131-313-1313", @"141-414-1414",nil];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.names.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    
    if( cell == nil)
    {
        cell = [[UITableViewCell alloc] init];
    }
    cell.textLabel.text = [self.names objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = [self.phones objectAtIndex:indexPath.row];
    cell.imageView.image = [UIImage imageNamed:@"Rose"];
    return cell;
}


@end

Download

Download the Contact List App from here

Sunday, July 20, 2014

iOS Tutorial - Part 15 - Add new file Xcode

Add a Model


Video Description 
We talked about communication between View and Controller, now it's time to talk about the Model. In tip calculator app we had only View and Controller. What would be the model in this application? The calculation method could be our Model (updateResult). We can separate this method and add in in a new class.

Add new File in Xcode

In Xcode, open File/New/File..., from the opening window, make sure on left hand side menu select iOS/Cocoa Touch. Select Objective-C Class and hit next. In the next view, in the first field you can specify your file name like TipCalculatorModel. In the second field you specify the subclass of the file that you want to create. Because we want to create a model, we can add NSObject as a subclass of our class. Hit next and then hit create. It adds TipCalculatorModel.h and TipCalculatorModel.m
We move updateResult contents into TipCalculatorModel and modify it like bellow:
- (NSMutableDictionary *)updateResult
{
    float tipAmount = self.tipPercentage * self.billAmount / 100;
    float totalBill = tipAmount + self.billAmount;
    NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
    
    [results setValue:[NSString stringWithFormat:@"Tip amount: %f", tipAmount] forKey:@"tipAmount"];
    [results setValue:[NSString stringWithFormat:@"Total: %f",totalBill] forKey:@"totalBill"];
    
    return results;
}
Because we don't have label we removed all UILabel properties and instead we define tipPercentage and billAmount property in TipCalculatorModel. These two properties will be set from the controller, which is ViewController class. The calculations stays the same. We removed the NSNumber wrappers just to simplify the method, instead we used stringWithFormat method. Last change for TipCalculatorModel is to make this method and two properties public then other classes can see their methods. We do this by adding the properties and the method name in header file (TipCalculatorModel.h) file like bellow:
#import <Foundation/Foundation.h>

@interface TipCalculatorModel : NSObject
@property (nonatomic, assign) int tipPercentage;
@property (nonatomic, assign) float billAmount;
- (NSMutableDictionary *)updateResult;
@end
Then we have to import the Model in our controller, we only import .h file.
#import "TipCalculatorModel.h"
Now we can create a property that is representing our model.
@property (nonatomic, strong) TipCalculatorModel *tipCalculatorModel;
Finally we modify the updateResult method in ViewController like bellow:
- (void)updateResult
{
    self.tipCalculatorModel = [[TipCalculatorModel alloc] init];
    self.tipCalculatorModel.tipPercentage = self.tipPercentageSlider.value;
    self.tipCalculatorModel.billAmount =[self.totalField.text floatValue];
    self.tipAmountLabel.text = [self.tipCalculatorModel.updateResult objectForKey:@"tipAmount"];
    self.resultLabel.text = [self.tipCalculatorModel.updateResult objectForKey:@"totalBill"];
    [self.totalField resignFirstResponder];
}
We create an instance of TipCalculatorModel and then allocate memory and initialize it. We set the tipPercentage property to the slider value. Since we have tipPercentage property in our model so we don't need instance variable tipPercentage in ViewController class.

All of the code for this tutorial

ViewController.m File

#import "ViewController.h"
#import "TipCalculatorModel.h"

@interface ViewController () <UITextFieldDelegate>

@property (nonatomic, strong) TipCalculatorModel *tipCalculatorModel;

@property (weak, nonatomic) IBOutlet UITextField *totalField;
@property (weak, nonatomic) IBOutlet UILabel *tipPercentageLabel;
@property (weak, nonatomic) IBOutlet UISlider *tipPercentageSlider;
@property (weak, nonatomic) IBOutlet UILabel *tipAmountLabel;
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;

@end


@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.totalField.delegate = self;
}


- (IBAction)tipPercentageChanged {
    self.tipPercentageLabel.text = [NSString stringWithFormat:@"Tip Percentage %d%%", self.tipCalculatorModel.tipPercentage];
    [self updateResult];
}

- (IBAction)calculatePressed {
    [self updateResult];
}

- (void)updateResult
{
    self.tipCalculatorModel = [[TipCalculatorModel alloc] init];
    self.tipCalculatorModel.tipPercentage = self.tipPercentageSlider.value;
    self.tipCalculatorModel.billAmount =[self.totalField.text floatValue];
    self.tipAmountLabel.text = [self.tipCalculatorModel.updateResult objectForKey:@"tipAmount"];
    self.resultLabel.text = [self.tipCalculatorModel.updateResult objectForKey:@"totalBill"];
    [self.totalField resignFirstResponder];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self updateResult];
    return YES;
}

@end

TipCalculatorModel.h

#import <Foundation/Foundation.h>

@interface TipCalculatorModel : NSObject
@property (nonatomic, assign) int tipPercentage;
@property (nonatomic, assign) float billAmount;
- (NSMutableDictionary *)updateResult;
@end

TipCalculatorModel.m

#import "TipCalculatorModel.h"

@interface TipCalculatorModel ()

@end

@implementation TipCalculatorModel


- (NSMutableDictionary *)updateResult
{
    float tipAmount = self.tipPercentage * self.billAmount / 100;
    float totalBill = tipAmount + self.billAmount;
    NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
    
    [results setValue:[NSString stringWithFormat:@"Tip amount: %f", tipAmount] forKey:@"tipAmount"];
    [results setValue:[NSString stringWithFormat:@"Total: %f",totalBill] forKey:@"totalBill"];
    
    return results;
}

@end

Download

Download the Tip Calculator App from here.

Saturday, July 12, 2014

iOS Tutorial - Part 14 - UITextFieldDelegate

UITextFieldDelegate


Video Description 

UITextFieldDelegate

Delegate performs methods on behalf of another object. There are lots of Delegate methods for many different objects. For instance, the Text Field object can't do anything on its own. Instead, it uses a delegate to perform actions. If you press the enter key on the on screen keyboard, the text field asks the delegate object to perform a specific method, textFieldShouldReturn. If the delegate you set for your text field does not have a textFieldShouldReturn method, the text field will not know what to do when you press the enter button.

Tip Calculator with Return button

We can enhance Tip Calculator app in previous session by adding UITextFieldDelegate. We want to add the following options to the application:
1. Make the return key on the keyboard work
2. Dismiss the keyboard once user clicks on the calculate button or the return key on the keyboard

Steps to declare built-in delegates

1- Declare the delegate name

We can declare the delegate name either in .h file or .m file.
Declare in .h file:
@interface ViewController : UIViewController <UITextFieldDelegate>
Declare in .m file:
@interface ViewController () <UITextFieldDelegate>

2- Put the delegate equal to self

By putting delegate equal to self, we tell the compiler that we want to implement the delegate methods. Most of the time, the best place to put the delegate method equal to self is in viewDidLoad (View lifecycle method).
self.totalField.delegate = self;

3- Add the delegate method

The last but not the least is adding the desired delegate method. For example in this tutorial in order to make the return key on keyboard working, we need to use the UITextFieldDelegate. This delegate has a method called: textFieldShouldReturn.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    //Add whatever you want to do when the user presses the return key on the keyboard
    return YES;
}

Dismiss keyboard

In order to dismiss the keyboard we need to use a method called resignFirstResponder. It's very easy to use, you just send a message from your textField to this method like bellow:
[self.yourTextFieldName resignFirstResponder]; 

All of the code for this tutorial

//
//  ViewController.m
//  TipCalculatorWithReturn
//
//  Created by Hamid on 7/6/14.
//  Copyright (c) 2014 HuxTek. All rights reserved.
//

#import "ViewController.h"

@interface ViewController () <UITextFieldDelegate>
{
    int tipPercentage;
}
@property (weak, nonatomic) IBOutlet UITextField *totalField;
@property (weak, nonatomic) IBOutlet UILabel *tipPercentageLabel;
@property (weak, nonatomic) IBOutlet UISlider *tipPercentageSlider;
@property (weak, nonatomic) IBOutlet UILabel *tipAmountLabel;
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;

@end

//2. Put delegate = self
//3. Use the delegate methods

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.totalField.delegate = self;
}


- (IBAction)tipPercentageChanged {
    self.tipPercentageLabel.text = [NSString stringWithFormat:@"Tip Percentage %d%%", tipPercentage];
    [self updateResult];
}

- (IBAction)calculatePressed {
    [self updateResult];
}

- (void)updateResult
{
    tipPercentage = self.tipPercentageSlider.value;
    float billAmount = [self.totalField.text floatValue];
    float tipAmount = tipPercentage * billAmount / 100;
    float totalBill = tipAmount + billAmount;
    NSNumber *totalBillWrapper = [NSNumber numberWithFloat:totalBill];
    NSNumber *tipAmountWrapper = [NSNumber numberWithFloat:tipAmount];
    self.tipAmountLabel.text = [NSString stringWithFormat:@"Tip amount: %@", [tipAmountWrapper stringValue]];
    self.resultLabel.text = [NSString stringWithFormat:@"Total: %@",[totalBillWrapper stringValue]];
    [self.totalField resignFirstResponder];

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self updateResult];
    return YES;
}

@end

Download

Download the TipCalculatorWithReturn App from here

Sunday, July 6, 2014

iOS Tutorial - Part 13 - Tip Calculator App, UISlider

Tip Calculator

 

Video Description 
Here are the code for the application that is described in this video with bunch of comments.
#import "ViewController.h"

@interface ViewController ()
{
    int tipPercentage;
}
@property (weak, nonatomic) IBOutlet UITextField *totalField;
@property (weak, nonatomic) IBOutlet UILabel *tipPercentageLabel;
@property (weak, nonatomic) IBOutlet UISlider *tipPercentageSlider;
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;
@property (weak, nonatomic) IBOutlet UILabel *tipAmountLabel;

@end

@implementation ViewController

- (IBAction)calculatePressed {
    [self updateResult];
}

- (IBAction)tipPercentageChanged {
    self.tipPercentageLabel.text = [NSString stringWithFormat:@"Tip Percentage %d%%", tipPercentage];
    [self updateResult];
}

- (void)updateResult
{
    //Get the value of the slider
    tipPercentage = self.tipPercentageSlider.value;
    //Convert the totalField text filed into the float value and assign it to a float local variable
    float billAmount = [self.totalField.text floatValue];
    //Calculate the tip amount 
    float tipAmount = tipPercentage * billAmount / 100;
    //Calculate the total bill amount
    float totalBill = billAmount + tipAmount;
    //Wrap the totalBill with NSNumber in order to get the string value of float variable
    NSNumber *totalBillWrapper = [NSNumber numberWithFloat:totalBill];
    //Wrap the tipAmount with NSNumber in order to get the string value of float variable
    NSNumber *tipAmountWrapper = [NSNumber numberWithFloat:tipAmount];
    //Set the value of labels
    self.tipAmountLabel.text = [NSString stringWithFormat:@"Tip amount: %@",[tipAmountWrapper stringValue]];
    self.resultLabel.text = [NSString stringWithFormat:@"Total: %@",[totalBillWrapper stringValue]];
}

@end

Download

Download the Tip Calculator App from here

Tuesday, June 24, 2014

iOS Tutorial - Part 12 - View and Controller communication, View Lifecycle

View and Controller communications, View Lifecycle 

 

Video Description 

View and Controller communication

In the Model View Controller design pattern we have communications between View and Controller. If Controller wants to send message to the view, it uses IBOutlet. If View wants to send message to the controller that for example some button pressed or the slider has changed it uses IBAction.

View Lifecycle

A series of methods that are sent to the View Controller when things happened. For example if we want to initialize some parameters before view appears to the user, we should use view lifecycle methods. Using these methods means overriding them. Because we override these methods, the first line of each method we should call the super (super class) and the name of the method. Here are the important view lifecycle methods:

viewDidLoad

The most important view lifecycle method is this method. This is a great place for initialization because it will be called only one time during the whole lifecycle and also all outlets are set. But do not initialize things that are related to geometry because at this point we can't be sure if we are on iPhone 5 size or 4 or iPad ...
- (void)viewDidLoad
{
    [super viewDidLoad]; //Always add this line as the first line of code for this method
    //Do initialization
}

viewWillAppear

This method is called each time that the view appears to the screen so it's not a good place for initialization because it could be called more than one time during the lifecycle. But it's a good place for updating the view.
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //Do updating the view
}

viewWillDisappear

This will be called a moment before view disappear from the screen. This is a good place to save the data to the storage. For example remembering the scroll position or saving what user typed so far, in order to retrieve it once s/he comes back to the view.
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    //Save Data
}

Sunday, June 8, 2014

iOS Tutorial - Part 11 - Converter App, IBOutlet, UITextField, UILabel, IBAction

Convert Miles to Feet App


Video Description 

IBOutlet

Identifier used to identify a property so Interface Builder can synchronize the display and connection of outlets with Xcode.
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;

UITextField


is a control that displays editable text and sends an action message to a target object when the user presses the return button. You typically use this class to gather small amounts of text from the user and perform some immediate action, such as a search operation, based on that text. It has a method called "text" that returns the value that user typed.
@property (weak, nonatomic) IBOutlet UITextField *milesField;

NSString *numberThatUserTyped = self.milesField.text;

UILabel

Implements a read-only text view. You can use this class to draw one or multiple lines of static text, such as those you might use to identify other parts of your user interface. It has a method called "text" that we can set the value of the label.
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;
self.resultLabel.text = @"The result";

IBAction

Use this type as the return type of any action methods defined in your project. It returns nothing (void), it just a way that Xcode understands it's target action connection.
- (IBAction)convertPressed {
    
}

Source code

//
//  ViewController.m
//  ReviewSession
//
//  Created by HuxTek on 5/25/14.
//  Copyright (c) 2014 HuxTek. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *milesField;
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;
@end

@implementation ViewController

- (IBAction)convertPressed {
    float miles = [self.milesField.text floatValue];
    // 1 miles = 5280.0 feet
    float feet = miles * 5280.0;
    self.resultLabel.text = [[NSNumber numberWithFloat:feet] stringValue];
}

@end

Download

Download converter App from here

Sunday, May 25, 2014

iOS Tutorial - Part 10 - Review

Review


Video Description 

Warnings

Xcode shows warning with yellow rectangle at the beginning of the line of the code that has problem. You can see the description of the warning by clicking on the rectangle. If the description of the warning is more than a line, you can hover the warning to show the full description of the warning.
In order to force the Xcode compiler to have a warning, we can use #warning message like bellow:
#warning Description of the warning

Errors

Xcode shows compile errors with red signs. The build will fail if application contains any error.

(nonatomic, strong)

nonatomic: Not thread safe. You can read the full description of this attribute here
strong: Strong pointer to an object. It means keep the memory for the thing that this property points to, in the heap,as long as I or anyone else has strong pointer to it. Full description could be found here
weak: Weak pointer to an object.

#import

In order to include other classes or other frameworks we use #import. We import only .h files. The format for importing classes is as follow:
#import "ViewController.h"
The format for importing a framework is as follow:
#import ""

Why self?

If you define a property and you want to call that property, you need to use self at the beginning of the name of the property. For local or instance variables we don't need to use self. If you are familiar with Java development, self is more like this in Java.

Dot notations and square bracket notation

You may have noticed dot notations in objective-c. They both do the same thing, accessing the methods.Use dot notation only for setters and getters, but for calling a method, use square bracket notation.
self.myTextField.text.length
The equivalent for the above line is as follow:
[[[self myTextField] text] length];
We can use the combination of dot notation and bracket notation like bellow:
[self.myTextField.text length];

MVC

Model-View-Controller
Full explanation of MVC design pattern in objective-c can be found here (Minute 14:18 until 26:00).

Wednesday, April 30, 2014

iOS Tutorial - Part 9 - NSNumber, id Type

NSNumber, id Type

Video Description 
 

NSNumber

It defines a set of methods specifically for setting and accessing the value.
@property (nonatomic, strong) NSNumber *myNumber;
numberWithInt
A wrapper around int to convert it to an object.
int myInt = 2;
self.myNumber = [NSNumber numberWithInt:myInt]; 
NSNumber has other useful methods for the other primitive types. Methods like: numberWithDouble, numberWithFloat, numberWithBool, numberWithChar, ...
Primitive types
Here are the important primitive types in Objective-C: int, BOOL, float, char, double, short, long.
stringValue
You can convert int type into string by using NSNumber method.
NSString *myStrig = [self.myNumber stringValue];
We have some similar methods like floatValue, intValue, boolValue, shortValue, doubleValue that can convert primitives into each other.

Type id

When we don't know the type of an object we use id as a type. It is useful when we want to assign a variable to a type but we are not sure what kind of object we receive (We will have more examples in the future).
@property (nonatomic, strong) id UnknownP;

Sunday, April 13, 2014

iOS Tutorial - Part 8 - Local Variable, NSDictionary, NSMutableDictionary

Local Variables, NSDictionary, NSMutableDictionary


Video Description 

Local Variables

You can define a local variable and in the same line you can also initialize it by allocating memory for it like bellow:
NSArray *myArray = [[NSArray alloc] init];
NSString *myLocalString = [[NSString alloc] init];

Useful methods of NSDictionary

The NSDictionary class declares the programmatic interface to objects that manage immutable associations of keys and values. We can declare and initialize a dictionary with keys and values with this method dictionaryWithObjectsAndKeys
NSDictionary *myDict = [NSDictionary dictionaryWithObjectsAndKeys:
                            @"value0", @"key0",
                            @"value1", @"key1",
                            @"value2", @"key2",
                            nil];

count
Returns the number of keys or values (number of keys and values are equal)
NSLog(@" %d", myDict.count);

objectForKey:key
Returns the value for the specified key
NSLog(@" %@", [myDict valueForKey:@"value0"]);
allKeys
Returns an array containing all keys in the dictionary
NSLog(@" %@", [myDict allkeys]);
allValues
Returns an array containing all values in the dictionary
NSLog(@" %@", [myDict allValues]);

Useful methods of NSMutableDictionary

setObject:anObject forKey:key
Adds an object with specified key to the dictionary
[myMuteDict setObject:@"Apple" forKey:@"ios"];
[myMuteDict setObject:@"Google" forKey:@"android"];

removeObjectForKey:key
Removes an object that has the specified key
[myMuteDict removeObjectForKey:@"android"];

removeAllObjects
Removes all of the objects from the dictionary
[myMuteDict removeAllObjects];

Sunday, February 16, 2014

iOS Tutorial - Part 7 - NSArray, NSMutableArray

Download finished project from here: Google Drive Download Link

NSArray, NSMutableArray


Video Description
NSArray and its subclass NSMutableArray manage ordered collections of objects called arrays. NSArray creates static arrays, and NSMutableArray creates dynamic arrays. You can use arrays when you need an ordered collection of objects. Here is the documentation of this class.

Initialize NSArray

We already know how to define NSArray property and also how to synthesize it. But let's log the value of the array and see what would we get.
Define the property:
@property (nonatomic, strong) NSArray *myArray;
Synthesize it:
@synthesize myMutableArray = _myMutableArray;
Log it like bellow:
NSLog(@" %@", self.myArray);
We expect that the result shows an empty array but The result will be null. Why? Because we have not initialized the array. Before initializing the array, there is no memory allocated for this array. By initializing the array we allocate memory for it then we can send message to that array and get a log for it. The best place to initialize the array property is in it's getter.

Equivalent for Synthesize

As I mentioned in tutorial part 4 When we synthesize properties, in fact we are creating setter and getter for that property. If we want to manually create the setter and getter for the property, we have something like bellow:
Setter
- (void)setMyArray:(NSArray *)myArray
{
    _myArray = myArray;
}

Getter
- (NSArray *)myArray
{
    return _myArray;
}

We need to modify the getter to initialize our array whenever we need the array. We allocate memory like bellow:
- (NSArray *)myArray
{
    if (_myArray == nil) _myArray = [[NSArray alloc] init];
    return _myArray;
}
The if statement above means that, if myArray is null, allocate memory for it and then initialize it for me. Now if we log the array, it shows an empty array. Since we don't change anything in setter method we can delete it.

Useful methods of NSArray

arrayWithObjects
You can define array items by using this method like bellow:
    
self.myArray = [NSArray arrayWithObjects:@"object zero",@"object one" , nil];

count
Returns number of items that array holds
NSLog(@" %d", self.myArray.count);
objectAtIndex:
Returns the value of the item that is located in the specified index
NSLog(@" %@", [self.myArray objectAtIndex:1]);
lastObject
Returns the value of the last object of the array
    NSLog(@" %@", [self.myArray lastObject]);

Useful methods of NSMutableArray

NSMutableArray has all of NSArray methods, plus the following methods:
addObject
Adds an object to the end of the array
[self.myMutableArray addObject:@"object 1"];
insertObject: atIndex:
Inserts an specified item to the array at specified index
[self.myMutableArray insertObject:@"Hi" atIndex:1];
removeObjectAtIndex:
Removes the object at specified index
[self.myMutableArray removeObjectAtIndex:0];
removeLastObject
Removes the last object of the array
[self.myMutableArray removeLastObject];

All of this tutorial code

//
//  ViewController.m
//  HelloWorld
//
//  Created by HuxTek on 1/19/14.
//  Copyright (c) 2014 HuxTek. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) NSArray *myArray;
@property (nonatomic, strong) NSMutableArray *myMutableArray;

@end

@implementation ViewController
@synthesize myArray = _myArray;
@synthesize myMutableArray = _myMutableArray;


//Setter for myArray
- (void)setMyArray:(NSArray *)myArray
{
    _myArray = myArray;
}

//Getter for myArray
- (NSArray *)myArray
{
    //Check if the array is null, allocate memory for it and then initilize it
    if (_myArray == nil) _myArray = [[NSArray alloc] init];
    return _myArray;
}

//Getter for myMutableArray
- (NSArray *)myMutableArray
{
    if (_myMutableArray == nil) _myMutableArray = [[NSMutableArray alloc] init];
    return _myMutableArray;
}

//The following method is View life cycle (Don't worry about it now I will dedicate special session for view life cyle. I used it here because I wanted to send message to console
-(void) viewDidLoad {
    [super viewDidLoad];
    
    //NSArray
    
    //Log static values
    NSLog(@" %@", self.myArray);
    //Result: ()
    self.myArray = [NSArray arrayWithObjects:@"object zero",@"object one" , nil];
    NSLog(@" %@", self.myArray);
    /* Result:
    (
     "object zero",
     "object one"
     )
     */
    
    
    // %d ==> for integer type
    // %g ==> for float type
    NSLog(@" %d", self.myArray.count);
    //Result: 2
    
    NSLog(@" %@", [self.myArray objectAtIndex:1]);
    //Result: object one
    
    NSLog(@" %@", [self.myArray lastObject]);
    //Result: object two

    //NSMUtableArray
    [self.myMutableArray addObject:@"object 0"];
    NSLog(@" %@", self.myMutableArray);
    /* Result:
     (
     "object 0"
     )
     */
    
    [self.myMutableArray addObject:@"object 1"];
    NSLog(@" %@", self.myMutableArray);
    /* Result:
     (
     "object 0",
     "object 1"
     )
     */
    
    [self.myMutableArray insertObject:@"Hi" atIndex:1];
    NSLog(@" %@", self.myMutableArray);
    /* Result:
     (
     "object 0",
     Hi,
     "object 1"
     )
    */
    
    [self.myMutableArray removeObjectAtIndex:0];
    NSLog(@" %@", self.myMutableArray);
    /* Result:
     (
     Hi,
     "object 1"
     )
     */
    
    
    [self.myMutableArray removeLastObject];
    NSLog(@" %@", self.myMutableArray);
    /* Result:
     (
     Hi
     )
     */

}

@end
Download finished project from here: Google Drive Download Link

Thursday, February 13, 2014

iOS Tutorial - Part 6 - NSLog, NSString, Documentation, Comment

NSString, NSLog


Video Description
One of the important frameworks in Objective-C is NSString, there are a lot of useful methods in this frameworks that could save you multiple lines of codes. In this tutorial I will discuss some of useful ones. If you want to see all of the methods you can read the documentation here : NSString Documentation

NSLog

In order to send message to console we use NSLog API.
NSLog(@" %@", @"Hello Console");

%@: reruns the description of the object that is passed after comma (,)
@"": returns whatever string value that is between quotation ""

How to access the value of property

We access the property inside of the instance methods by putting word "self" and the "." and then name of the property. For example for the property like this :
@property (nonatomic, strong) NSString *st1;

If we want to get the value, we put it on the right side of the equation:
  = self.st1

If we want to set the value, we put it on the left side of the equation:
 self.st1 = //Whatever value

How to put comments in Objective-C

Comments are not compiled in Objective-C. They are just for developers to put brief explanation of their code. If your comment is just one line, you can add // at the beginning of the line and start typing. But if your comment is more than one line it's better to use multiple comment line format which starts with /* and you can end it with */

Useful NSString methods

stringByAppendingString
By using this method you can concatenate two strings together. See example at the end of this tutorial to learn how to use it.
stringByAppendingFormat
By using this method you can give your string(s) a format that you want. See example at the end of this tutorial to learn how to use it.
//
//  ViewController.m
//  HelloWorld
//
//  Created by HuxTek on 1/19/14.
//  Copyright (c) 2014 HuxTek. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) NSString *st1;
@property (nonatomic, strong) NSString *st2;
@property (nonatomic, strong) NSString *st3;
@end

@implementation ViewController
@synthesize st1 = _st1;
@synthesize st2 = _st2;
@synthesize st3 = _st3;


//The following method is View life cycle (Don't worry about it now I will dedicate special session for view life cyle. I used it here because I wanted to send message to console
-(void) viewDidLoad {
    [super viewDidLoad];
    //Log static values
    NSLog(@" %@", @"Hello Console");
    //Result: Hello Console
    
    
    //Set a vale for property (We set the value of st1 to be "string one"
    self.st1 = @"string one";
    
    //If we want to log the value of the st1, we should write
    NSLog(@" %@", self.st1);
    //Result: string one
    
    
    //Get a vlue of propert
    //We want to get a value of st1 and set it for st2
    //In simple word we want to copy st1 into st2
    self.st2 = self.st1;
    
    //If we want to log the value of the st2, we should write
    NSLog(@" %@", self.st2);
    //Result: string one
    
    
    //How to comments
    //One line comment by adding // at the begging of line
    //Compiler will not compile the comments
    
    /*
        Multiple comment line
        line 2
        line 3 ...
     */
    
    
    //Append (concatinate st1 to st2 by the follwing method)
    //Open bracket [ and close bracket ] is for sending message to objects
    //We send message to st1 to append st2 and at the same time we set st3 to be the result value of this operation
    
    //Lets change the value of st2 so we can differentiate st1 from st2
    self.st2 = @"string two";
    self.st3 = [self.st1 stringByAppendingString:self.st2];
    NSLog(@" %@", self.st3);
    //Result: string onestring two
    
    
    
    //String format
    //If we want to have format like bellow
    //(string one) -> **string two**
    //We should use a method called: stringByAppendingFormat
    self.st3 = [self.st3 stringByAppendingFormat:@"(%@) -> **%@**", self.st1, self.st2];
    NSLog(@" %@", self.st3);
    //Result: (null)
    
    // Result is null because we have not initialized st3
    // We initialize it with empty string before setting it to the desired format
    self.st3 = @"";
    self.st3 = [self.st3 stringByAppendingFormat:@"(%@) -> **%@**", self.st1, self.st2];
    NSLog(@" %@", self.st3);
    //Result: (string one) -> **string two**
}


@end

Saturday, February 8, 2014

iOS Tutorial - Part 5 - Foundation Frameworks

Foundation Frameworks (Property and variable types)


Video Description

NSObject

NSObject is the root class of most Objective-C class hierarchies. Through NSObject, objects inherit a basic interface to the runtime system and the ability to behave as Objective-C objects (Don't worry if you don't understand the definition, we will talk about it later).

NSString & NSMutableString


In order to define a String type variable or property in Objective-C language we use NSString like bellow:
@property (nonatomic, strong) NSString *myString;

If you want to modify the existing string, instead of NSString type you should use NSMutableString, which is mutable version of the NSString
@property (nonatomic, strong) NSMutableString *myMutableString;

NSArray & NSMutableArray


Ordered collection of objects. In order to define an Array type variable or property in Objective-C language we use NSArray like bellow:
@property (nonatomic, strong) NSArray *myArray;
If we want to add or remove object to the array or any other modification we have to use NSMutableArray type like bellow:
@property (nonatomic, strong) NSMutableArray *myMutableArray;

NSDictionary & NSMutableDictionary


Look up objects using a key to get a value. In order to define a dictionary with keys and values in Objective-C language we use NSDictionary like this:
@property (nonatomic, strong) NSDictionary *myDictionary;
If we want to have a modifiable version of NSDictionary we should use NSMutableDictionary type like bellow:
@property (nonatomic, strong) NSMutableDictionary *myMutableDictionary;

NSNumber

Object wrapper around primitive types like int, float, double, BOOL, etc. It is useful when you want to put these primitive types in an NSArray or NSDictionary. We can define it like bellow:
@property (nonatomic, strong) NSNumber *myNumber;