2

I have made an application for IOS, in which I am using sqlite database, database is local in application. Now I have given the functionality the application is downloading data from internet & put it in local database & show infront of user. I have given this functionality on - (void)viewDidLoad so that when application is downloading data, it stop working till it finish downloading part, for this user need to wait to interact with application.

Now I wants to functionality a thread run in background of application which will connect the internet & update the application without interfering user. please help me.

My code of download & save image is this:

 -(void)Download_save_images:(NSString *)imagesURLPath :(NSString *)image_name   
   {                              

      NSMutableString *theString = [NSMutableString string];

    // Get an image from the URL below    
      UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:NSURL  URLWithString:imagesURLPath]]];        
      NSLog(@"%f,%f",image.size.width,image.size.height);        
     NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    // If you go to the folder below, you will find those pictures
     NSLog(@"%@",docDir);    
    [theString appendString:@"%@/"];
    [theString appendString:image_name];
    NSLog(@"%@",theString);
    NSLog(@"saving png");
    NSString *pngFilePath = [NSString stringWithFormat:theString,docDir];
    NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(image)];
    [data1 writeToFile:pngFilePath atomically:YES];  

    NSLog(@"saving image done");

    [image release];
   // [theString release];
}

when i am debugging application i seen my application taking more time at below line:

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:NSURL  URLWithString:imagesURLPath]]];
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Anupam Mishra
  • 3,408
  • 5
  • 35
  • 63

5 Answers5

3

You can also use NSOperationQueue and NSBlockOperation if you find GCD difficult.

NSBlockOperation *operation=[[NSBlockOperation alloc] init];

[operation addExecutionBlock:^{
    //Your code goes here

}];

NSOperationQueue *queue=[[NSOperationQueue alloc] init];
[queue addOperation:operation];

In GCD You could achieve the same using

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
   //Your Code to download goes here

    dispatch_async(dispatch_get_main_queue(), ^{
       //your code to update UI if any goes here

    });
});

Use either of the API Depending upon your needs. Check this thread which discuss about NSOperationQueue vs GCD for more info.

Community
  • 1
  • 1
Shahzin KS
  • 1,001
  • 8
  • 8
  • i am using GCD as u have given , but at the time of download images my application is going to hang till the images din't finish download. please suggest m the way. – Anupam Mishra Apr 25 '13 at 06:36
1

Questions like these were asked hundreds of times before. I suggest you do a quick search on this. Also there is a topic in apple documentation covering this area thoroughly. here

Basically you can do this with operation queues or dispatch queues. There are some code snippets given above by Avi & Amar.

I'd like to add something since you seem to be unfamiliar with the topic & you mentioned there are web requesting involved.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

    // Dont DIRECTLY request your NSURL Connection in this part because it will never return data to the delegate...
//  Remember your network requests like NSURLConnections must be invoked in mainqueue
// So what ever method you're invoking for NSURLConnection it should be on the main queue

        dispatch_async(dispatch_get_main_queue(), ^{
                // this will run in main thread. update your UI here.
        });
    });

I've given small example below. you can generalise the idea to match your needs.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        // Do your background work here

        // Your network request must be on main queue. this can be raw code like this or method. which ever it is same scenario. 
        NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];
        dispatch_async(dispatch_get_main_queue(), ^{

            [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *res, NSData *dat, NSError *err)
             {
                 // procress data

                 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

                     // back ground work after network data received

                     dispatch_async(dispatch_get_main_queue(), ^{

                         // finally update UI
                     });
                 });
             }];
        });
    });
nsuinteger
  • 1,503
  • 12
  • 21
  • actually i am using https://www.parse.com (parse) cloud to download data. so there is no URl request like NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]]; – Anupam Mishra Apr 25 '13 at 06:50
0

You can us GCD, like that:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    // put here your background code. This will run in background thread.

    dispatch_async(dispatch_get_main_queue(), ^{
            // this will run in main thread. update your UI here.
    });
})

But you need to understand how blocks work for example. Try it.

Avi Tsadok
  • 1,843
  • 13
  • 19
  • i am using GCD as u have given , but at the time of download images my application is going to hang till the images din't finish download. please suggest m the way. – Anupam Mishra Apr 25 '13 at 06:35
  • Don't understand -> you want it to hang? You want the UI to be free for interactions? Please add your code to the question. – Avi Tsadok Apr 25 '13 at 06:39
  • i want to UI to free to be interact . – Anupam Mishra Apr 25 '13 at 06:46
  • Ok, so if you run all "heavy code", like image downloading in the place I wrote : '// put here your background code. This will run in background thread.' The UI will be free. – Avi Tsadok Apr 25 '13 at 06:48
0

Use GCD

create your dispatch object

dispatch_queue_t yourDispatch;
yourDispatch=dispatch_queue_create("makeSlideFast",nil);

then use it

dispatch_async(yourDispatch,^{
//your code here

//use this to make uichanges on main thread
dispatch_async(dispatch_get_main_queue(), ^(void) {
});


});

Do ui on main thread only by using

dispatch_async(dispatch_get_main_queue(), ^(void) {
});

Then release it

dispatch_release(yourDispatch);

Here is tutorial

amar
  • 4,285
  • 8
  • 40
  • 52
  • i am using GCD as u have given , but at the time of download images my application is going to hang till the images din't finish download. please suggest m the way. – Anupam Mishra Apr 25 '13 at 06:37
  • you need to dwnload in aasync mode did ya see the tutorial? – amar Apr 25 '13 at 06:42
0

There are a lot of ways:

1 . Grand Central Dispatch

dispatch_async(dispatch_get_global_queue(0, 0), ^{
  //Your code
});

2 . NSThread

[NSThread detachNewThreadSelector:@selector(yourMethod:) toTarget:self withObject:parameterArray];

3 . NSObject - performSelectorInBackground

[self performSelectorInBackground:@selector(yourMethod:) withObject:parameterArray];
Midhun MP
  • 103,496
  • 31
  • 153
  • 200
  • i am using GCD as u have given , but at the time of download images my application is going to hang till the images din't finish download. please suggest m the way. – Anupam Mishra Apr 25 '13 at 06:37