74

I want to know how to call my function on the main thread.

How do I make sure my function is called on the main thread?

(this follows a previous question of mine).

Community
  • 1
  • 1
user236739
  • 1,323
  • 2
  • 15
  • 21
  • I would imagine only classes that call your delegate methods using `[NSObject performSelectorOnMainThread]` can be considered *safe*. Otherwise if the object just calls `[NSObject performSelector]` your delegate methods are running in the context of the caller's thread. – trojanfoe Jul 20 '12 at 15:37

4 Answers4

168

This will do it:

[[NSOperationQueue mainQueue] addOperationWithBlock:^ {

   //Your code goes in here
   NSLog(@"Main Thread Code");

}];
starball
  • 20,030
  • 7
  • 43
  • 238
shoughton123
  • 4,255
  • 3
  • 21
  • 23
  • It does, thanks. Do you know if this is subject to the same kind of restrictions as meccans' answer (which is the GCD version I guess), say 'don't call this from the main thread'? – user236739 Jul 23 '12 at 10:27
  • 2
    Well I just find this way easier because if you do it this way you don't have to make a new method every time you want to do something on the main thread. – shoughton123 Jul 23 '12 at 12:55
  • 1
    This helped me with a socket programming mysterious hang when upgrading my XCode to the latest iOS 6.1 simulator. The code was writing to a socket immediately after reading some data from it. For some strange reason, that worked like a charm in iOS 5.1 simulator, but not in 6.0 or 6.1 - using this suggestion to execute the write operation on the socket in the main thread solved my problem, and it works in all simulator versions and devices! – Luis Artola Mar 22 '13 at 14:50
  • 1
    So I was using the code block in the above answer: (dispatch_sync(dispatch_get_main_queue(), ^{ //Your code goes in here NSLog(@"Main Thread Code"); });) since gcd is known to work well however, I ran into an issue where the main thread wouldn't take priority and the app would stall in one of the iPod5's I have. I switched to using the NSOperationQueue instead and it worked fine. Weird odd case but I thought, I'd document it here. – C0D3 May 02 '14 at 15:23
  • So this, unlike dispatch_get_main_queue, you can do directly on the main thread? – mkc842 May 28 '14 at 17:14
  • This is better as I can "throw" whatever code inside without having to "design" a function for a performselector. Also, whatever that's executed from within there goes on the main thread as well. Thanks! – lppier Aug 31 '14 at 03:52
  • Although I prefer this option (looks nicer) it is slow with hard UI (e.g. progress updates lag). For that you should use dispatch_async. – Recycled Steel Oct 22 '15 at 15:00
139

When you're using iOS >= 4

dispatch_async(dispatch_get_main_queue(), ^{
  //Your main thread code goes in here
  NSLog(@"Im on the main thread");       
});
CarlJ
  • 9,461
  • 3
  • 33
  • 47
  • 4
    Just so the OP is clear, this is not something you'd want to do if you're already on the main thread. – Firoze Lafeer Jul 20 '12 at 15:44
  • What horrible thing will happen, exactly? (just for curiosity) – Nicolas Miari Jul 23 '12 at 07:13
  • 5
    the main thread freezes! here is the source: http://stackoverflow.com/a/7817170/644629 – CarlJ Jul 23 '12 at 07:17
  • 2
    Also see http://stackoverflow.com/questions/5662360/gcd-to-perform-task-in-main-thread (you should be able to use dispatch_async and not have a problem when on the main thread). – Chris Prince Jan 07 '14 at 21:05
  • Would using dispatch_sync work without issue too? – CyberMew Feb 22 '16 at 08:57
  • yes, it would work without issues if you call `dispatch_sync` on a background thread, but you will run into a deadlock if you call `dispatch_sync` on the main thread with `dispatch_get_main_queue` – CarlJ Feb 24 '16 at 08:17
49

there any rule I can follow to be sure that my app executes my own code just in the main thread?

Typically you wouldn't need to do anything to ensure this — your list of things is usually enough. Unless you're interacting with some API that happens to spawn a thread and run your code in the background, you'll be running on the main thread.

If you want to be really sure, you can do things like

[self performSelectorOnMainThread:@selector(myMethod:) withObject:anObj waitUntilDone:YES];

to execute a method on the main thread. (There's a GCD equivalent too.)

Amy Worrall
  • 16,250
  • 3
  • 42
  • 65
12

i think this is cool, even tho in general its good form to leave the caller of a method responsible for ensuring its called on the right thread.

if (![[NSThread currentThread] isMainThread]) {
    [self performSelector:_cmd onThread:[NSThread mainThread] withObject:someObject waitUntilDone:NO];
    return;
}
Sean Danzeiser
  • 9,141
  • 12
  • 52
  • 90