iOS - Ensure execution on main thread [duplicate]
Asked Answered
A

4

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).

Asthenia answered 20/7, 2012 at 15:20 Comment(1)
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.Parthenos
S
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.)

Sibeal answered 20/7, 2012 at 15:36 Comment(1)
How would you go about the case where you spawn a thread to run code in the background?Wyandotte
C
168

This will do it:

[[NSOperationQueue mainQueue] addOperationWithBlock:^ {

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

}];
Corrosive answered 20/7, 2012 at 15:38 Comment(7)
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'?Asthenia
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.Corrosive
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!Walkyrie
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.Soften
So this, unlike dispatch_get_main_queue, you can do directly on the main thread?Glyn
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!Servo
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.Caras
L
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");       
});
Ludhiana answered 20/7, 2012 at 15:41 Comment(6)
Just so the OP is clear, this is not something you'd want to do if you're already on the main thread.Fabe
What horrible thing will happen, exactly? (just for curiosity)Epizoic
the main thread freezes! here is the source: https://mcmap.net/q/24016/-dispatch_sync-on-main-queue-hangs-in-unit-testLudhiana
Also see #5662860 (you should be able to use dispatch_async and not have a problem when on the main thread).Additional
Would using dispatch_sync work without issue too?Stavros
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_queueLudhiana
S
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.)

Sibeal answered 20/7, 2012 at 15:36 Comment(1)
How would you go about the case where you spawn a thread to run code in the background?Wyandotte
T
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;
}
Tallulah answered 7/3, 2013 at 0:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.