Monday, April 28, 2014

Blocks and Multithreading in iOS

Blocks are important in iOS programming because they are used to implement multithreading with GCD (Grand Central Dispatch).  A block is a chunk of code contained in {}.  To indicate the beginning of a block use a caret (^). Here is a block that prints a string. 
^{
    NSString *type = "Demo";
    NSLog(@" %@", type);
};
We use the caret (^) character to define the beginning of a block literal, and if there are any arguments they are contained in () followed by the block code itself contained in {}. An example of a block that takes an int as an argument and returns the square value. 
^(int value){
    return value*value;
}
You don't have to declare the return type of a block, it can be inferred from the code in the block. Most of the time we pass the block to a method directly, but we can also assign it to a block variable. The syntax for declaring a block variable is "return_type (^name) (arguments)" If we declare a block variable "square" and assign to it the block we used in the previous example, it would look like this. 
int (^square) (int) = ^(int value){
    return value*value;
};
You can call this block just like a function. 
int square_value = square(5);
We can also create a type definition for a variable that holds a block by using typedef. The syntax is similar to declaring a block variable name "typedef return_type (^type_name) (arguments)" Then we can declare the block variables with "type_name block_name = ^(arguments){...}"

Blocks are closures, therefore they have access to local variables when the block is created. Local variables are read only. If you want to be able to change the value of local variables, they need to be declared with __block.

To implement multithreading in iOS we use GCD (Grand Central Dispatch). Any operation that takes a long time to execute might lock the UI (User Interface) while it is being performed. For example, anything network related, like getting an image from a remote server. If the image is large enough, it might take a minute or two to download. If we don't use a different thread for downloading the image, the whole app will be locked for the duration of the time it takes to download the image. In cases like this it is a good idea to use GCD to improve the user experience. This is where blocks become very useful to programmers.

GCD is a C API, therefore it is not object oriented API. The most basic use of GCD is to create a queue, and then to put blocks on that queue to be executed in a different thread by the system. The function used to create a queue and put a block on one are as follows 
//to create a queue
dispatch_queue_t dispatch_queue_create(const char *label, NULL);

//to put a block on a queue
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block):
^dispatch_block_t is a prototype of blocks submitted that takes no arguments and doesn't return anything. Let's say we have a method that downloads an xml file from the internet. 
-(void)fetchXML
{
    NSString *URLString = @"example.com/example.xml";
    NSURL *URL = [NSURL URLWithString:[URLString
                        stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
    NSData *dataXML = [NSData dataWithContentsOfURL:URL];
    NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:dataXML];
    [xmlParser setDelegate:self];
    BOOL success = [xmlParser parse];
    // test the result
    if (success) {
        NSLog(@"No errors");
    } else {
        NSLog(@"Error");
    }
}
To execute the fetching of the file on a different thread, we need to do the following modifications to our code. Create a queue and then put the code as a block on that queue. 
-(void)fetchXML
{
    dispatch_queue_t fetchQueue = dispatch_queue_create("fetch xml", NULL);
    dispatch_async(fetchQueue, ^{
        NSString *URLString = @"example.com/example.xml";
        NSURL *URL = [NSURL URLWithString:[URLString
                         stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
        NSData *dataXML = [NSData dataWithContentsOfURL:URL];
        NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:dataXML];
        [xmlParser setDelegate:self];
        BOOL success = [xmlParser parse];
        // test the result
        if (success) {
            NSLog(@"No errors");
        } else {
            NSLog(@"Error");
        }
   });
}
There is just one more rule about using GCD for multithreading. When we have code that makes changes to UIKit objects, we need to dispatch that block of code in the main queue. The way to get the main queue is with "dispatch_get_main_queue". 
dispatch_async(dispatch_get_main_queue(), ^{....});



Regards : http://code-and-coffee.blogspot.in/

Friday, April 4, 2014

iPhone 6 Will make headache for iOS Developer ?

Apple iPhone 6 keeps the aspect ratio as same as iPhone 5/c/s, so that it can continue to use a 1136×640 display. All apps in iPhone 6 work as if it is in the older version. It is happy to say that developers won't be overloaded to update their applications to support the larger display. 


Working with UIRefreshControl





             The class reference of UIRefreshControl is short, hinting at how easy it is to get started with this addition of the UIKit framework. The UIRefreshControl class directly descends from UIControl, which means that setting up an instance ofUIRefreshControl is not much different from creating and configuring any other UIKit control. After instantiating an instance of the UIRefreshControl class, you assign it to the new refreshControl property of a table view controller object (UITableViewController or a subclass of it). The table view controller takes care of properly positioning and displaying the refresh control. As with any otherUIControl subclass, you attach a target-action pair to a specific event,UIControlEventValueChanged in the case of UIRefreshControl.

      If you run the application in the iPhone Simulator, you should see an empty table view. Take a look at the implementation of the viewDidLoad method shown below. We initialize the refresh control and add a target and action for the UIControlEventValueChangedevent of the refresh control. Finally, the refresh control is assigned to therefreshControl property of the table view controller. Of course, therefreshControl property is also new for iOS 6.



- (void)viewDidLoad {
    [super viewDidLoad];
    // Initialize Refresh Control
    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    // Configure Refresh Control
    [refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
    // Configure View Controller
    [self setRefreshControl:refreshControl];
}



Before we build and run the project once more, we need to implement therefresh: action in the view controller's implementation file. The idea behind the refresh control is in some ways similar to UIKit's activity indicator view (UIActivityIndicatorView), that is, you are responsible for showing and hiding it. Hiding the refresh control is as simple as sending it a message ofendRefreshing



- (void)refresh:(id)sender
{
    NSLog(@"Refreshing");

// End Refreshing
    [(UIRefreshControl *)sender endRefreshing];
}



There are many libraries that try to mimic the original "pull to refresh" functionality, but it is nice to see that Apple has finally embraced this neat concept and included it in the UIKit framework.