Sunday, January 25, 2015

iOS Tutorial - Part 27 - HttpRequest POST, GET (NSURLConnection) II

HttpRequest POST, GET (NSURLConnection) II


Video Description 
This is the second part of NSURLConnection tutorial. If you have not read or watched the first part, click here to watch it first. In this part we will learn how to create a GET and POST request.

How to create GET request

The following method will do the GET request
- (void)httpGetRequest
{
    NSString *str = @"http://content.guardianapis.com/search?api-key=test";
    str = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:str];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:GET];
    self.restApi.delegate = self;
    [self.restApi httpRequest:request];
}
In the first line we add the url address that we want to send the GET request. In the second line we convert the special characters of the url in first line. In the third like we convert the str into URL type that Objective-C can read it as an URL. In the fourth line we create our actual request with the URL we created. In the fifth line we specify the Http type (Here it's GET). The sixth line we are setting restApi delegate equal to self to implement RestApi class. In the last line we call RestAPI class to send our request (RestApi is created in previous session).

How to create POST request

- (void)httpPostRequest
{
    NSString *postBody = @"api-key=test";
    NSString *str = @"http://content.guardianapis.com/search";
    str = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:str];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:POST];
    [request setHTTPBody:[postBody dataUsingEncoding:NSUTF8StringEncoding]];
    self.restApi.delegate = self;
    [self.restApi httpRequest:request];
}
It's exactly like sending GET request, the only difference is that it has 2 more lines. The first line and the seventh line. In the first line specifies the post body, which may includes post parameters. In the seventh line we attach the post body to the request.

What to do next

Click here for the third part of Http Request

Sunday, January 18, 2015

iOS Tutorial - Part 26 - HttpRequest POST, GET (NSURLConnection) I

HttpRequest POST, GET (NSURLConnection) I


Video Description 
One of the most popular functionality that many apps have is being able to send and receive data over internet. As you may know this service is called Http Request. The type of request could be POST, GET, DELETE, ... . Once you understand one type of request, you can use for other types of requests. Just to simplify the subject, it's divided into multiple sessions. In this session we talk about an API for Http Request, which is NSURLConnection.

RestAPI

I have created a class called "RestAPI". This class is designed to implement NSURLConnection delegate methods. Delegate methods that we are going to implement in this class are as follow:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.receivedData appendData:data];
}
This method appends the response data that is received from server or web. You may ask why we should append the data, It'd because most of the time server or web divides into separate parcels and sends it one by one. It's our job to append this data into a single object. We store the data in self.receivedData property. This property has a type called "NSMutableData". we define this property like bellow:
@property (nonatomic, strong) NSMutableData *receivedData;
We initialize it in it's setter like bellow:
- (NSMutableData *)receivedData
{
    if (!_receivedData)
    {
        _receivedData = [[NSMutableData alloc] init];
    }
    return _receivedData;
}
The next NSURLConnection delegate method is:
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"%@", error.description);
}
If any error happens during the request, this method will be called. In this tutorial for the sake of simplicity we won't handle network errors, we just log the error in console and nothing else but you may handle the error properly. The other important delegate method is as follow:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self.delegate getReceivedData:self.receivedData sender:self];
    self.delegate = nil;
    self.requestConnection = nil;
    self.receivedData = nil;
}
When the response for our request becomes available this method will be called. After we are done with the response that we get, we put everything to nil because we may want to use them again through the application and they should be initialized again. The first line of the implementation of this method is calling a delegate method of "RestAPIDelegate", which is in RestAPI.h. In Session 18 (Create Protocol (Delegate), prepareForSegue) we have learnt how to create a protocol and what are they good for. In RestAPI.h file we have created a delegate method in order to be notified whenever the response becomes ready. This delegate has one method which is used in connectionDidFinishLoading.
@class RestAPI;
@protocol RestAPIDelegate
- (void)getReceivedData:(NSMutableData *)data sender:(RestAPI *)sender;
@end
Lastly we have a public method in RestAPI.h which is
- (void)httpRequest:(NSMutableURLRequest *)request;
Each class that wants to do Http Request should call this method by passing request argument. In next session we will talk how to create this request.


What to do next

Click here for the second part of Http Request

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