Check whether or not the current thread is the main thread

Objective CIphoneMultithreadingCocoaxamarin.ios

Objective C Problem Overview


Is there any way to check whether or not the current thread is the main thread in Objective-C?

I want to do something like this.

  - (void)someMethod
  {
    if (IS_THIS_MAIN_THREAD?) {
      NSLog(@"ok. this is main thread.");
    } else {
      NSLog(@"don't call this method from other thread!");
    }
  }

Objective C Solutions


Solution 1 - Objective C

Have a look at the NSThread API documentation.

There are methods like

- (BOOL)isMainThread

+ (BOOL)isMainThread

and + (NSThread *)mainThread

Solution 2 - Objective C

In Swift3

if Thread.isMainThread {
    print("Main Thread")
}

Solution 3 - Objective C

If you want a method to be executed on the main thread, you can:

- (void)someMethod
{
    dispatch_block_t block = ^{
		// Code for the method goes here
	};

	if ([NSThread isMainThread])
	{
		block();
	}
	else
	{
		dispatch_async(dispatch_get_main_queue(), block);
	}
}

Solution 4 - Objective C

If you want to know whether or not you're on the main thread, you can simply use the debugger. Set a breakpoint at the line you're interested in, and when your program reaches it, call this:

(lldb) thread info

This will display information about the thread you're on:

thread #1: tid = 0xe8ad0, 0x00000001083515a0 MyApp`MyApp.ViewController.sliderMoved (sender=0x00007fd221486340, self=0x00007fd22161c1a0)(ObjectiveC.UISlider) -> () + 112 at ViewController.swift:20, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1

If the value for queue is com.apple.main-thread, then you're on the main thread.

Solution 5 - Objective C

The following pattern will assure a method is executed on the main thread:

- (void)yourMethod {
    // make sure this runs on the main thread 
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:_cmd/*@selector(yourMethod)*/
                               withObject:nil
                            waitUntilDone:YES];
        return;
    }
    // put your code for yourMethod here
}

Solution 6 - Objective C

Two ways. From @rano's answer,

[[NSThread currentThread] isMainThread] ? NSLog(@"MAIN THREAD") : NSLog(@"NOT MAIN THREAD");

Also,

[[NSThread mainThread] isEqual:[NSThread currentThread]] ? NSLog(@"MAIN THREAD") : NSLog(@"NOT MAIN THREAD");

Solution 7 - Objective C

void ensureOnMainQueue(void (^block)(void)) {
    
    if ([[NSOperationQueue currentQueue] isEqual:[NSOperationQueue mainQueue]]) {
        
        block();
        
    } else {
        
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            
            block();
            
        }];
        
    }
    
}

note that i check the operation queue, not the thread, as this is a more safer approach

Solution 8 - Objective C

For Monotouch / Xamarin iOS you can perform the check in this way:

if (NSThread.Current.IsMainThread)
{
	DoSomething();
}
else
{
	BeginInvokeOnMainThread(() => DoSomething());
}

Solution 9 - Objective C

Details

  • Swift 5.1, Xcode 11.3.1

Solution 1. Detect any queue

Get current DispatchQueue?

Solution 2. Detect only main queue

import Foundation

extension DispatchQueue {
    
    private struct QueueReference { weak var queue: DispatchQueue? }

    private static let key: DispatchSpecificKey<QueueReference> = {
        let key = DispatchSpecificKey<QueueReference>()
        let queue = DispatchQueue.main
        queue.setSpecific(key: key, value: QueueReference(queue: queue))
        return key
    }()

    static var isRunningOnMainQueue: Bool { getSpecific(key: key)?.queue == .main }
}

Usage

if DispatchQueue.isRunningOnMainQueue { ... }

Sample

func test(queue: DispatchQueue) {
    queue.async {
        print("--------------------------------------------------------")
        print("queue label: \(queue.label)")
        print("is running on main queue: \(DispatchQueue.isRunningOnMainQueue)")
    }
}

test(queue: DispatchQueue.main)
sleep(1)
test(queue: DispatchQueue.global(qos: .background))
sleep(1)
test(queue: DispatchQueue.global(qos: .unspecified))

Result (log)

--------------------------------------------------------
queue label: com.apple.root.background-qos
is running on main queue: false
--------------------------------------------------------
queue label: com.apple.root.default-qos
is running on main queue: false
--------------------------------------------------------
queue label: com.apple.main-thread
is running on main queue: true

Solution 10 - Objective C

Swift Version


if (NSThread.isMainThread()) {
    print("Main Thread")
}

Solution 11 - Objective C

> let isOnMainQueue = > (dispatch_queue_get_label(dispatch_get_main_queue()) == > dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))

check this answer from https://stackoverflow.com/a/34685535/1530581

Solution 12 - Objective C

Here is a way to detect what the current queue is
extension DispatchQueue {
    //Label of the current dispatch queue.
    static var currentQueueLabel: String { String(cString: __dispatch_queue_get_label(nil)) }

    /// Whether the current queue is a `NSBackgroundActivityScheduler` task.
    static var isCurrentQueueNSBackgroundActivitySchedulerQueue: Bool { currentQueueLabel.hasPrefix("com.apple.xpc.activity.") }

    /// Whether the current queue is a `Main` task.
    static var isCurrentQueueMainQueue: Bool { currentQueueLabel.hasPrefix("com.apple.main-thread") }
}

Solution 13 - Objective C

UPDATE: seems that is not correct solution, according to queue.h header as mentioned @demosten

The first thought was brought to me, when I was needed this functionality was the line:

dispatch_get_main_queue() == dispatch_get_current_queue();

And had looked to the accepted solution:

[NSThread isMainThread];

mine solution 2.5 times faster.

PS And yes, I'd checked, it works for all threads

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionfish potatoView Question on Stackoverflow
Solution 1 - Objective CranoView Answer on Stackoverflow
Solution 2 - Objective CdimohamdyView Answer on Stackoverflow
Solution 3 - Objective CbohernaView Answer on Stackoverflow
Solution 4 - Objective CEricView Answer on Stackoverflow
Solution 5 - Objective CT.J.View Answer on Stackoverflow
Solution 6 - Objective CTom HowardView Answer on Stackoverflow
Solution 7 - Objective CPeter LapisuView Answer on Stackoverflow
Solution 8 - Objective CDaniele D.View Answer on Stackoverflow
Solution 9 - Objective CVasily BodnarchukView Answer on Stackoverflow
Solution 10 - Objective CMichaelView Answer on Stackoverflow
Solution 11 - Objective CJerryZhouView Answer on Stackoverflow
Solution 12 - Objective CMark CaoView Answer on Stackoverflow
Solution 13 - Objective CHotJardView Answer on Stackoverflow