Question

Tearing my hair out on this, any thoughts or suggestions would be greatly appreciated.

I have an object that calls performSelectorOnMainThread:withObject:waitUntilDone: on itself from a child thread. This works fine 95% of the time. Every once in a while since iOS betas and now into release, a device will refuse to execute the performSelectorOnMainThread:withObject:waitUntilDone: calls... No error message, it doesn't crash, I can't make a device go into a state where it "fails" but once it's there it continues to fail until I either delete and re-install the app, or force it to quit, then adjust it's location services allowance, then launch it again, then re-adjust it's location services again back to normal... restarting the device does not fix it. Re-installing without deleting first doesn't fix it. It's very strange.... I know it works most of the time because most devices have no problems, however some devices fail somewhat regularly (every 3 or 4 days maybe). I know it's specifically that performSelectorOnMainThread:withObject:waitUntilDone: is not calling what it should because I've got a failing device now, and I've put an NSLog into the method that should be called. It function fine, but on the failing device, when performSelectorOnMainThread:withObject:waitUntilDone: is used to call that method the NSLog shows it's not being run...

This started happening with iOS 5 betas and again, happens on release. It happens most often on 2 of my devices, but on none of the other 10 devices I have personally tested on. I assumed it was just my device from some hiccup in the beta, but it happens on my brand new 4S which never touched beta, as well as on one user's iPad 2 (not on my iPad 2).

I really don't know where to look. I tell it to execute and it usually does on almost every device, but the same line gets no response and no errors etc. on some...

Was it helpful?

Solution

performSelectorOnMainThread:withObject:waitUntilDone can be wonky sometimes. Have you thought about trying to use lib dispatch?

You can create a block and post it on the main thread like this:

dispatch_async(dispatch_get_main_queue(), ^{
    <do work here>
});

This would have the same save affect as using performSelectorOnMainThread:withObject:waitUntilDone http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1

OTHER TIPS

A Thread's RunLoop has several different modes. It is possible that during the time you make your call the main thread is running in a mode different than the default one (which is the one targeted by performSelectorOnMainThread:withObject:WaitUntilDone:.

Consider using performSelectorOnMainThread:withObject:waitUntilDone:modes:
See Apple's documentation.

Also - GCD (libdispatch) is awesome, but it won't protect you from cooking yourself a deadlock: Consider the case where your method is running on the main thread and you're calling:

dispatch_sync(dispatch_get_main_queue(), ^{
    <do work here>
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top