Search code examples
iosbackground-processnsthread

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.


Solution

  • 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;
    }