I wrote a test to experiment with RestKit using blocks. I thought that the RKRequest.onDidLoadResponse would need to contain a dispatch_async() call to get the response on the main UI thread, though to my surprise this turned out to cause a runtime exception, so I took it out and I could update the interface quite fine.
My code in question is as follows:
- (IBAction)loadSeasons:(UIButton *)sender {
[[RKClient sharedClient] get:@"/api/v1/seasons" usingBlock:^(RKRequest* req) {
req.onDidLoadResponse = ^(RKResponse* res) {
NSLog(@"Request Performed: %@", res.bodyAsString);
self.textResponse.text = res.bodyAsString;
//dispatch_async(dispatch_get_main_queue(), ^{
// NSLog(@"In main queue: %@", res.bodyAsString);
//});
};
}];
}
If I uncomment the dispatch_async block I get the exception. So how do I know when I need to use this and when I should not need to? Should I test for something that tells me if the code being executed is on the main thread or not?
I am new to Objective-C and it’s early days for me so I do apologise for what may be a newbie question.
UPDATE: When uncommenting the code above the following happens:
- The console outputs the text
(lldb)in blue, no other information is provided. - A break on
libobjc.A.dylibobjc_msgSend:is shown in the editor on0x1c2009b: movl 8(%edx), %ediwith the message in green:Thread 1: EXC_BAD_ACCESS (code=1, address=0x40000008)`.
To answer your question you can check your current thread by calling
[NSThread isMainThread]. However, you DONT need to do this for your issue and in fact its perfectly legal to dispatch an execution block to the main thread if you are already running in the main thread.The crash is because of the way that variables are stored when executing a block. When the first block is completed the stack memory used by the variable can be overwritten, so by the time your async
NSLogstatement runs in the second block, your variablereshas been destroyed, so its pointing to garbage when its used in your log statement, triggering a crash.For completeness, research
__blockvariable declarations. To makeresreferenceable in your second dispatch block I believe you’d have to declare it as a__blockvariable to move it to heap by declaring this in your first block:__block RKResponse* response = res;and then usingresponsein your dispatched log statement.