Ravi_Parmar
Ravi_Parmar

Reputation: 12329

perform background task on different thread in iOS

How to preform certain operation in background on different thread, if it is executed on main thread it is blocking the UI of my app. any one have any idea how to do it?

even if it prints NSLog in background it will be fine. i want to run following thing in no matter even if user presses HOME button. in my viewController i did this :

- (IBAction)btnStartClicked:(UIButton *)sender {
    [NSThread detachNewThreadSelector:@selector(StartBGTask) toTarget:self withObject:nil];
     }

-(void)StartBGTask{
    [[[UIApplication sharedApplication] delegate] performSelector:@selector(startThread)];  
  }

and in appDelegate.m i have this method

 -(void) startThread {
 @autoreleasepool {
    for (int i = 0; i < 100; i++) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"current progress %d", i);
        });
        [NSThread sleepForTimeInterval:1];
    }
   }
 }

it prints integer from 1 to 100 on interval of 1 second.

Upvotes: 3

Views: 6914

Answers (3)

Rishabh Srivastava
Rishabh Srivastava

Reputation: 3745

Add these properties to your .h file

@property (nonatomic, strong) NSTimer *updateTimer;
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;

Now replace btnStartClicked method with this,

-(IBAction)btnStartClicked:(UIButton *)sender {
    self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
                                                        target:self
                                                      selector:@selector(calculateNextNumber)
                                                      userInfo:nil
                                                       repeats:YES];
    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"Background handler called. Not running background tasks anymore.");
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
    }];
    
}

 -(void)calculateNextNumber{
    @autoreleasepool {
      // this will be executed no matter app is in foreground or background
    }
}

and if you need to stop it use this method,

 - (IBAction)btnStopClicked:(UIButton *)sender {

    [self.updateTimer invalidate];
    self.updateTimer = nil;
    if (self.backgroundTask != UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
    }
    i = 0;
}

Upvotes: 8

Lucas Eduardo
Lucas Eduardo

Reputation: 11675

A really easy way to accomplish what you want:

-(IBAction)btnStartClicked:(UIButton *)sender {
   [self performSelectorInBackground:@selector(codeInBakground) withObject:nil];
}

-(void)codeInBakground
{
   for (int i = 0; i < 100; i++) {
         NSLog(@"current progress %d", i);
        [NSThread sleepForTimeInterval:1]; //the code will print one number in each second, until 100
    }
}

In this way, your main thread, and your UI won't be blocked.

Upvotes: 0

Boran
Boran

Reputation: 959

Check GCD for more information.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //code in background
    });

Upvotes: 6

Related Questions