Reputation: 12329
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
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
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
Reputation: 959
Check GCD for more information.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code in background
});
Upvotes: 6