Objective-C
background thread
multithreading
iOS development
concurrency

How to use the background thread in Objective-C?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Using a background thread in Objective-C is mainly about keeping expensive work off the main thread so the interface stays responsive. The safest pattern is to run heavy work asynchronously, then hop back to the main queue only for UI updates.

Know What Must Stay on the Main Thread

On iOS and macOS, the main thread is responsible for user-interface work. That includes updating labels, reloading table views, changing constraints, and most other AppKit or UIKit interactions. If you run a long network request, image resize, JSON parse, or database operation there, the app feels frozen.

The goal of background threading is not to make everything concurrent. It is to move the slow, non-UI parts away from the main thread while keeping UI code predictable.

Use Grand Central Dispatch for Most Work

For modern Objective-C code, Grand Central Dispatch, usually called GCD, is the default tool. It is simpler than managing raw NSThread instances and is the right answer for most one-off background tasks.

objective-c
1dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
2    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://example.com/data.json"]];
3
4    NSError *error = nil;
5    id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
6
7    dispatch_async(dispatch_get_main_queue(), ^{
8        if (error) {
9            self.statusLabel.text = @"Load failed";
10        } else {
11            self.statusLabel.text = [NSString stringWithFormat:@"Loaded %@", jsonObject];
12        }
13    });
14});

The outer dispatch_async runs work in the background. The inner dispatch_async returns to the main queue so the label update happens safely.

Choose the Right Queue Priority

GCD lets you describe how urgent the work is. That matters because not all background jobs should compete equally for system resources.

  • use QOS_CLASS_USER_INITIATED for work triggered by the user that should finish soon
  • use QOS_CLASS_UTILITY for longer tasks such as imports or exports
  • use QOS_CLASS_BACKGROUND for work the user does not need to notice immediately

Example:

objective-c
1dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
2
3dispatch_async(queue, ^{
4    [self rebuildSearchIndex];
5
6    dispatch_async(dispatch_get_main_queue(), ^{
7        self.statusLabel.text = @"Index rebuilt";
8    });
9});

Picking a reasonable quality-of-service class helps the system schedule work more intelligently.

Use NSOperationQueue When You Need Structure

If you need cancellation, dependencies, or a queue you can pause, NSOperationQueue is often better than bare GCD blocks.

objective-c
1NSOperationQueue *queue = [[NSOperationQueue alloc] init];
2queue.maxConcurrentOperationCount = 2;
3
4NSBlockOperation *downloadOp = [NSBlockOperation blockOperationWithBlock:^{
5    [NSThread sleepForTimeInterval:1.0];
6}];
7
8NSBlockOperation *uiOp = [NSBlockOperation blockOperationWithBlock:^{
9    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
10        self.statusLabel.text = @"Background work finished";
11    }];
12}];
13
14[uiOp addDependency:downloadOp];
15
16[queue addOperation:downloadOp];
17[queue addOperation:uiOp];

This approach is helpful when background work has multiple steps or when you want explicit ordering between tasks.

NSThread Still Exists, but Use It Sparingly

NSThread gives you more direct control over threads, but most app code does not need that level of manual management. It is best reserved for legacy code or specific situations where you truly need a custom thread lifecycle.

objective-c
1[NSThread detachNewThreadSelector:@selector(doWorkInBackground) toTarget:self withObject:nil];
2
3- (void)doWorkInBackground
4{
5    @autoreleasepool {
6        NSString *result = [NSString stringWithFormat:@"Finished on %@", [NSThread currentThread]];
7
8        dispatch_async(dispatch_get_main_queue(), ^{
9            self.statusLabel.text = result;
10        });
11    }
12}

If you choose NSThread, remember that background threads may need their own autorelease pool when doing Objective-C object work.

Keep Shared State Simple

Running code off the main thread introduces data consistency problems if several threads read and write the same mutable objects. The safest habit is to keep background work local, produce an immutable result, and hand that result back to the main thread.

For example, parse JSON into model objects in the background, then assign the finished array to a property on the main thread. Avoid having the background block mutate collections that the UI is also using.

Common Pitfalls

The most common mistake is doing the slow work in the background and then accidentally updating the UI from that same background queue. Another frequent issue is launching many tiny background tasks with no coordination, which makes code harder to reason about without improving performance. Developers also reach for NSThread too early even though GCD or NSOperationQueue already solves the problem with less code. Finally, shared mutable state is a recurring source of crashes once background work starts touching objects that the main thread also uses.

Summary

  • Keep UI code on the main thread and move expensive non-UI work to the background.
  • Use GCD for most asynchronous background tasks in Objective-C.
  • Use NSOperationQueue when you need cancellation, dependencies, or more structure.
  • Reserve NSThread for special cases or legacy code.
  • Return to the main queue before updating labels, views, or other UI objects.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.