Sunday, February 22, 2015

iOS Tutorial - Part 29 - Asynchronous HttpRequest

Asynchronous HttpRequest


Video Description 
In first, second and third session of HttpRequest we have learnt how to create a synchronous HttpRequest, in this session we will learn how to make a Asynchronous calls. We also learn how to add activity indicator to show the user some network calls are going on in the background.

Spinning wheel (Activity indicator)

Drag and drop Activity Indicator from Object Library from right side bar of Xcode. Add it to the storyboard of the project that we created in the previous session. Then control + drag it to it's class to create a property for it. Now in viewDidLoad before httpGetRequest method start the activity indicator like bellow:
[self.activityIndicator startAnimating];
Then we can stop it and hide it or remove it from the view like bellow:
    
    [self.activityIndicator stopAnimating];        //Stop animating
    self.activityIndicator.hidden = YES;           //Hide it
    [self.activityIndicator removeFromSuperview];  //Remove it from view

How to send Asynchronous NSURLRequest

For Asynchronous HttpRequest we don't need RestApi class that we created in last three sessions. instead we use the following method:
 

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
    {
            //Do whatever you want after response received
            [self getReceivedData:data];
    }];
getReceivedData:data is a method that we created in last tutorial we changed it a little bit since we didn't need RestApi class so we removed the sender argument and also we changed the type od NSMutableData into NSData. If we want to handle errors we have:
 
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
    {
        if (!connectionError && [data length] > 0)
        {
            [self getReceivedData:data];
        }
        else
        {
            NSLog(@"%@", connectionError.description);
        }
    }];

Download

Download this App from here

Sunday, February 1, 2015

iOS Tutorial - Part 28 - HttpRequest POST, GET (NSURLConnection) III

HttpRequest POST, GET (NSURLConnection) III


Video Description 
In first and second session of Http request we have learned how to implement NSURLConnection delegate methods and also create Http GET and POST request. In the last session we will learn how to parse JSON format and show it in a tableView.

JSON content Type

If you copy paste the response from our Guardian News into this JSON formatter, and press Process button, you will see the JSON format in better view. If you collapse the first (-) buttons you will see it's a curly brace with something inside. This curly brace means the type of the response is dictionary. You can also say this fact by "key", "value" content. If you expand the response by taping on (+) button, and collapse the content of "response" by tapping on (-) you would see something like this
{  
   "response":{  }
}
It shows that "response" is a key and {} is it's value. Now if you expand the response value content and collapse the value of the "results", you would see something like this:
{  
   "response":{  
      "status":"ok",
      "userTier":"developer",
      "total":1732677,
      "startIndex":1,
      "pageSize":10,
      "currentPage":1,
      "pages":173268,
      "orderBy":"newest",
      "results":[  ]
   }
} 
If you notice the content of "results" is inside of Bracket []. It means that the content type of "results" is Array. The way we read JSON is based on the content type. If it's dictionary we should define NSDictionary but if the type is array we should define NSArray.

Read JSON format step by step

Since the whole response is dictionary we should define an NSDictionary and serialize the received data to make it human readable. We also handle any potential error with NSError.
- (void)getReceivedData:(NSMutableData *)data sender:(RestAPI *)sender
{
    NSError *error = nil;
    NSDictionary *receivedData =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
}
Now in order to get the value of "response" we should define another dictionary like bellow and we initializing it with the key called "response":
- (void)getReceivedData:(NSMutableData *)data sender:(RestAPI *)sender
{
    NSError *error = nil;
    NSDictionary *receivedData =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    NSDictionary *response = [[NSDictionary alloc] initWithDictionary:[receivedData objectForKey:@"response"]];
}
Then we have a "results" to parse. The type of results is array so we define an array like bellow:
    NSArray *results = [[NSArray alloc] initWithArray:[response objectForKey:@"results"]];
Now we have to iterate through the array items, we do this by for loop like bellow:
for (int i; i < results.count; i++)
    {
        NSDictionary *resultsItems = [results objectAtIndex:i];
        NSString *webTitle = [resultsItems objectForKey:@"webTitle"];
        [self.webTitles addObject:webTitle];
        NSString *sectionName = [resultsItems objectForKey:@"sectionName"];
        [self.sectionNames addObject:sectionName];
    }
Since the content of each item of array is type of dictionary, we defined resultsItems variable. Then inside of this dictionary we are looking for a key "webTitle" and "sectionName". These are the values that we are going to show it in our tableView. We store these inside of two arrays to access them later for filling our tableView.

Fill out the tableView with the fetched response

Now we just have to define a number of sections, which is 1 and then number of rows in each sections, which is equal to the number items in webTitle array. And finally we implement the important tableView delegate, which is for content of each cell.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

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


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    
    cell.textLabel.text = [self.webTitles objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = [self.sectionNames objectAtIndex:indexPath.row];
    
    return cell;
}

Reload tableView

The last thing we have to do is to reload the tableView to show the fetched results, it's very easy to implement and it should be in the getReceivedData method.
[self.tableView reloadData];

Download

Download this App from here