Reputation: 9515
I'm trying to create a single method for check what is the current thread and if it is different from the desired one, re-execute the (caller) method in the right thread.
I am using:
-(void)aMethod:(id)aParam
{
[self executeInRightThread];
...
}
This is the current code:
-(void)executeInRightThread
{
NSString * rightQueueLabel = [NSString stringWithCString:dispatch_queue_get_label(myQueue) encoding:NSUTF8StringEncoding];
NSString * currentQueueLabel = [NSString stringWithCString:dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) encoding:NSUTF8StringEncoding];
BOOL isInTheRightQueue = [currentQueueLabel isEqualToString:rightQueueLabel];
NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1]; // Example: 1 UIKit 0x00540c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:@""];
// NSLog(@"Stack = %@", [array objectAtIndex:0]);
// NSLog(@"Framework = %@", [array objectAtIndex:1]);
// NSLog(@"Memory address = %@", [array objectAtIndex:2]);
// NSLog(@"Class caller = %@", [array objectAtIndex:3]);
// NSLog(@"Function caller = %@", [array objectAtIndex:4]);
// NSLog(@"Line caller = %@", [array objectAtIndex:5]);
NSString * callerMethodName = [array objectAtIndex:4];
if ( !isInTheRightQueue )
{
dispatch_async(myQueue, ^{
[self performSelector:NSSelectorFromString(callerMethodName)];
});
}
}
The executeInRightThread
method works well but I don't know how to retrieve the caller method parameters (aParam in the example), I don't want pass the parameters to the executeInRightThread
method, the main aim is create something usable everywhere, without using blocks and without pass different parameters.
Upvotes: 0
Views: 349
Reputation: 32642
Use NSThread currentThread
to query the current thread. However, your question is a little confused, because you then specify the variable isInTheRightQueue
.
You cannot query the current queue - dispatch_get_current_queue()
is deprecated, and will not always return what you expect (and dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
has exactly the same problem). We ran into a case on iOS 8 where AVCaptureVideoOutput was configured to call us back on the main queue. In the call back, we found that the return result of dispatch_get_current_queue()
was not what we expected (we originally called setSampleBufferDelegate:... queue:dispatch_get_main_queue()
, but instead was:
(lldb) po dispatch_get_current_queue()
<OS_dispatch_queue: com.apple.avfoundation.videodataoutput.bufferqueue[0x170118e40] = { xrefcnt = 0x1, refcnt = 0x3, suspend_cnt = 0x0, locked = 1, target = com.apple.main-thread[0x1001be800], width = 0x0, running = 0x0, barrier = 1 }>
(lldb) p (char*)dispatch_queue_get_label(nil)
(char *) $4 = 0x000000017026f8c0 "com.apple.avfoundation.videodataoutput.bufferqueue"
(lldb) p (char*)dispatch_queue_get_label((dispatch_queue_t)[captureOutput sampleBufferCallbackQueue])
(char *) $6 = 0x00000001001af6b0 "com.apple.main-thread"
Notice that this is a queue targeting the main thread, rather than the main queue itself.
There is no mapping between queues and threads. Any queue that executes on a background thread - as opposed to the main thread - can execute on ANY background thread.
The normal case where you want to check the execution thread is if you need to execute code which affects the UI.
if(![NSThread isMainThread])
{
dispatch_sync(dispatch_get_main_queue(), ^{ .... });
}
If you need to verify that you have been called back on the correct background queue, then you may need to think more clearly about your application logic. However, if you really need to do this, why not do a dispatch_async to the relevant background queue. This will delay execution of your desired task, but since you're already in the background, this presumably doesn't matter.
Upvotes: 3