asiHttpRequest under iOS5 - objective-c

I am succesfuly using AsiHttpRequest library to make url connections in my apps. However, I upgrade to iOS5 and Reachability.m file is reporting some errors (4) on following functions:
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
#pragma unused (target, flags)
NSCAssert(info, #"info was NULL in ReachabilityCallback");
NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], #"info was the wrong class in ReachabilityCallback");
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: (Reachability *) info];
} // ReachabilityCallback()
- (BOOL) startNotifier {
SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) {
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
return YES;
}
}
return NO;
} // startNotifier
1sr error: in NSCAssert line, "Cast of C pointer type 'void' to Objective-C pointer type NSObject requires a bridged cast". Why happens and how to solve it?
ANSWER: you can disable ARC for each file. Go to build settings of your project and set the -fno-objc-arc flag on all the ASIHTTPRequest files (double click to edit text). Then you must remove ASIAuthenticationDialog and any references to it that are still generating errors. It works for me.

EDIT: I remember now and yes, the problem is ARC. But you can exclude files from being complied under ARC by setting the following compiler flag in Build Phases >> Compile Sources: -fno-objc-arc. If you select all the ASIHTTPRequest files and double-click, you can set the flag for all of them in one fell swoop.
ORIGINAL POST:
I've been using ASIHTTPRequest for a couple of weeks now and I remember reading a post somewhere about problems with Reachability, I just can't remember what it was exactly.
Anyway, this is what those lines in my Reachability.m look like:
//Start listening for reachability notifications on the current run loop
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
#pragma unused (target, flags)
NSCAssert(info, #"info was NULL in ReachabilityCallback");
NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], #"info was the wrong class in ReachabilityCallback");
//We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
// in case someone uses the Reachablity object in a different thread.
NSAutoreleasePool* pool = [NSAutoreleasePool new];
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification
object: (Reachability *) info];
[pool release];
} // ReachabilityCallback()
- (BOOL) startNotifier {
SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context)) {
if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
return YES;
}
}
return NO;
} // startNotifier

Related

macOS: Detect all application launches including background apps?

Newbie here. I'm trying to create a small listener for application launches, and I already have this:
// almon.m
#import <Cocoa/Cocoa.h>
#import <stdio.h>
#include <signal.h>
#interface almon: NSObject {}
-(id) init;
-(void) launchedApp: (NSNotification*) notification;
#end
#implementation almon
-(id) init {
NSNotificationCenter * notify
= [[NSWorkspace sharedWorkspace] notificationCenter];
[notify addObserver: self
selector: #selector(launchedApp:)
name: #"NSWorkspaceWillLaunchApplicationNotification"
object: nil
];
fprintf(stderr,"Listening...\n");
[[NSRunLoop currentRunLoop] run];
fprintf(stderr,"Stopping...\n");
return self;
}
-(void) launchedApp: (NSNotification*) notification {
NSDictionary *userInfo = [notification userInfo]; // read full application launch info
NSString* AppPID = [userInfo objectForKey:#"NSApplicationProcessIdentifier"]; // parse for AppPID
int killPID = [AppPID intValue]; // define integer from NSString
kill((killPID), SIGSTOP); // interrupt app launch
NSString* AppPath = [userInfo objectForKey:#"NSApplicationPath"]; // read application path
NSString* AppBundleID = [userInfo objectForKey:#"NSApplicationBundleIdentifier"]; // read BundleID
NSString* AppName = [userInfo objectForKey:#"NSApplicationName"]; // read AppName
NSLog(#":::%#:::%#:::%#:::%#", AppPID, AppPath, AppBundleID, AppName);
}
#end
int main( int argc, char ** argv) {
[[almon alloc] init];
return 0;
}
// build: gcc -Wall almon.m -o almon -lobjc -framework Cocoa
// run: ./almon
Note: when I build it, it will run fine, but if you do it with Xcode 10 on High Sierra, you will get ld warnings, which you can ignore, however.
My question: Is there a way to also detect a launch of a background application, e.g. a menu bar application like Viscosity etc.? Apple says that
the system does not post
[NSWorkspaceWillLaunchApplicationNotification] for background apps or
for apps that have the LSUIElement key in their Info.plist file.
If you want to know when all apps (including background apps) are
launched or terminated, use key-value observing to monitor the value
returned by the runningApplications method.
Here: https://developer.apple.com/documentation/appkit/nsworkspacewilllaunchapplicationnotification?language=objc
I would at least try to add support for background apps etc. to the listener, but I don't know how to go about it. Any ideas?
As the document suggests, you use Key-Value Observing to observe the runningApplications property of the shared workspace object:
static const void *kMyKVOContext = (void*)&kMyKVOContext;
[[NSWorkspace sharedWorkspace] addObserver:self
forKeyPath:#"runningApplications"
options:NSKeyValueObservingOptionNew // maybe | NSKeyValueObservingOptionInitial
context:kMyKVOContext];
Then, you would implement the observation method (using Xcode's ready-made snippet):
- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
if (context != kMyKVOContext)
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if ([keyPath isEqualToString:#"runningApplications"])
{
<#code to be executed when runningApplications has changed#>
}
}

Support NSDocument changes in an external editor?

I have an NSDocument with some simple code:
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
self.string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return YES;
}
If I change the file in an external editor, how do I get notified of this so I can handle it? I assume there is something built in for this, but I can't find it.
I'm looking for something built into NSDocument. I'm aware of FSEvent, but that seems too low level to do something very common for most document-based apps.
Since OS X v10.7, NSDocument provides a far simpler mechanism you can override in subclasses: -presentedItemDidChange.
Handling -presentedItemDidChange, Ignoring Metadata Changes
Just relying on this callback can produce false positives, though, when metadata change. That got on my nerves quickly for files stored in Dropbox, for example.
My approach to deal with this in general, in Swift, is like this:
class MyDocument: NSDocument {
// ...
var canonicalModificationDate: Date!
override func presentedItemDidChange() {
guard fileContentsDidChange() else { return }
guard isDocumentEdited else {
DispatchQueue.main.async { self.reloadFromFile() }
return
}
DispatchQueue.main.async { self.showReloadDialog() }
}
fileprivate func showReloadDialog() {
// present alert "do you want to replace your stuff?"
}
/// - returns: `true` if the contents did change, not just the metadata.
fileprivate func fileContentsDidChange() -> Bool {
guard let fileModificationDate = fileModificationDateOnDisk()
else { return false }
return fileModificationDate > canonicalModificationDate
}
fileprivate func fileModificationDateOnDisk() -> Date? {
guard let fileURL = self.fileURL else { return nil }
let fileManager = FileManager.default
return fileManager.fileModificationDate(fileURL: fileURL)
}
}
Now you have to update the canonicalModificationDate in your subclass, too:
In a callback from the "do you want to replace contents?" alert which I call -ignoreLatestFileChanges so you don't nag your user ad infitium;
In -readFromURL:ofType:error: or however you end up reading in contents for the initial value;
In -dataOfType:error: or however you produce contents to write to disk.
You want to register with the FSEvents API. Since 10.7, you can watch arbitrary files.
Potential duplicate of this question.
When I open a document in my document-based app, edit in in another application, and switch back to my app, the same method that you mentioned (readFromData:ofType:error:) is called with the new data. This method is called when you restore a previous version from the Versions browser, too.
You could then add a boolean instance variable to check whether it's being called because of an external update (in my case, I check whether one of my IBOutlets is initialized: if it's not, the document is being loaded for the first time). You might want to move your code that makes use of the string instance variable into some method that you can call if the document is already initialized, like this:
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
self.string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (self.isLoaded)
[self documentChanged];
return YES;
}
- (void)windowControllerDidLoadNib:(FCWindowController *)windowController {
self.isLoaded = YES;
[self documentChanged];
}
- (void)documentChanged {
// use self.string as you like
]
NSMetadataQuery seems to be the best way to monitor file and folder changes without polling and with a low cpu overhead.
Some basic code for watching a folder, you'd just want to set the filePattern to the filename and not the wildcard *
NSString* filePattern = [NSString stringWithFormat:#"*"];
NSString *watchedFolder = #"not/fake/path";
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
[query setSearchScopes:#[watchedFolder]];
NSString *itemName = (NSString*)kMDItemFSName;
[query setPredicate:[NSPredicate predicateWithFormat:#"%K LIKE %#", NSMetadataItemDisplayNameKey, filePattern]];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(queryFoundStuff:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[nc addObserver:self selector:#selector(queryFoundStuff:) name:NSMetadataQueryDidUpdateNotification object:query];
[query setNotificationBatchingInterval:0.5];
[query startQuery];
- (void)queryFoundStuff:(NSNotification *)notification {
[query disableUpdates];
NSLog(#"Notification: %#", notification.name);
NSMutableArray *results = [NSMutableArray arrayWithCapacity:query.resultCount];
for (NSUInteger i=0; i<query.resultCount; i++) {
[results addObject:[[query resultAtIndex:i] valueForAttribute:NSMetadataItemPathKey]];
}
// file has updated, do something
[query enableUpdates];
}
I've never been able to find an ideal solution to watching files for updates, NSFilePresenter sounds like it should be the appropriate high level solution, but from what I can tell it only works if the file is being edited by another App using NSFilePresenter also. I've also tried VDKQueue and SCEvents which wrap low level kernel events but have a cpu overhead.

Use Block in Objective C to find out if a BOOL has been set?

I'm new to Obj-c. I've got a class which sets a var boolean to YES if it's successful (Game Center login = successful), what it would be great to do, is somehow have a listener to that var that listens to when it is YES and then executes some code. Do I use a block for that? I'm also using the Sparrow framework.
Here's my code in my GameCenter.m file
-(void) setup
{
gameCenterAuthenticationComplete = NO;
if (!isGameCenterAPIAvailable()) {
// Game Center is not available.
NSLog(#"Game Center is not available.");
} else {
NSLog(#"Game Center is available.");
__weak typeof(self) weakSelf = self; // removes retain cycle error
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; // localPlayer is the public GKLocalPlayer
__weak GKLocalPlayer *weakPlayer = localPlayer; // removes retain cycle error
weakPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (viewController != nil)
{
[weakSelf showAuthenticationDialogWhenReasonable:viewController];
}
else if (weakPlayer.isAuthenticated)
{
[weakSelf authenticatedPlayer:weakPlayer];
}
else
{
[weakSelf disableGameCenter];
}
};
}
}
-(void)showAuthenticationDialogWhenReasonable:(UIViewController *)controller
{
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:controller animated:YES completion:nil];
}
-(void)authenticatedPlayer:(GKLocalPlayer *)player
{
NSLog(#"%#,%#,%#",player.playerID,player.displayName, player.alias);
gameCenterAuthenticationComplete = YES;
}
-(void)disableGameCenter
{
}
But I need to know from a different object if that gameCenterAuthenticationComplete equals YES.
You can use a delegate pattern. It's far easier to use than KVO or local notifications and it's used a lot in Obj-C.
Notifications should be used only in specific situations (e.g. when you don't know who wants to listen or when there are more than 1 listeners).
A block would work here but the delegate does exactly the same.
You could use KVO (Key-Value Observing) to watch a property of your object, but I'd rather post a NSNotification in your case.
You'll need to have the objects interested in knowing when Game Center login happened register themselves to NSNotificationCenter, then post the NSNotification in your Game Center handler. Read the Notification Programming Topics for more details !
If there is a single method to execute on a single delegate object, you can simply call it in the setter. Let me give a name to this property:
#property(nonatomic,assign, getter=isLogged) BOOL logged;
It's enough that you implement the setter:
- (void) setLogged: (BOOL) logged
{
_logged=logged;
if(logged)
[_delegate someMethod];
}
Another (suggested) way is to use NSNotificationCenter. With NSNotificationCenter you can notify multiple objects. All objects that want to execute a method when the property is changes to YES have to register:
NSNotificationCenter* center=[NSNotificationCenter defaultCenter];
[center addObserver: self selector: #selector(handleEvent:) name: #"Logged" object: nil];
The handleEvent: selector will be executed every time that logged changes to YES. So post a notification whenever the property changes:
- (void) setLogged: (BOOL) logged
{
_logged=logged;
if(logged)
{
NSNotificationCenter* center=[NSNotificationCenter defaultCenter];
[center postNotificationName: #"Logged" object: self];
}
}

Calling Obj-C Code from JavaScript via Console: Arguments get dropped?

Having a heck of a time with this one.
I've got a super-simple Cocoa app containing one WebView, a WebScripting API defined in the page, and a single NSObject defined on that API. When I turn on the debugger tools (in the embedded WebView), I can see the API on the JavaScript window object, and I can see my "api" property defined on that -- but when I call the API's "get" method, the arguments aren't being serialized -- when the Obj-C method gets called, the arguments are missing. See below, which hopefully illustrates:
I've combed through the docs, I've (apparently) set the appropriate methods to expose everything that needs to be exposed, and I can see the method being called. There has to be something stupid I'm missing, but as a relative newbie to this environment, I'm not seeing it.
Thanks in advance for your help!
Have you set WebKitDeveloperExtras to YES in your default user defaults when you send -[NSUserDefaults registerDefaults:]?
Depending on what version of Xcode you're using you could be getting a known error. If you're using LLDB on anything but the most recent version, it might not be giving you the right variables in the debugger. The solution has been to use GDB instead of LLDB until Apple fixes the problem. But I think they fixed the problem in the latest version. I'd change the debugger to use GDB and see if you're getting the right variables in Xcode. (Product-> Edit Scheme...-> Run -> Debugger). I came across this problem in iOS, though, so I don't know its applicability to OSX. Worth a try anyway.
I originally came across the problem here: https://stackoverflow.com/a/9485349/1147934
I process javascript in the main thread of my app from a local file stored in the apps directory. I check for beginning and ending tokens for the js functions I am executing and whether the function contains a variable.
Hopefully this can give you some good ideas for your issue. You could also do alerts in the js to see if the values post correctly as you run the app (I am sure you thought of that already, but it's worth mentioning.) Happy coding! I hope this helps!
in the .h file define:
NSMutableString *processedCommand;
NSArray *commandArguments;
In the .m file:
// tokens
#define kOpenToken #"<%%"
#define kCloseToken #"%%>"
// this will throw
-(void)executeJScriptCommand:(NSString *)aCommand {
[self performSelectorOnMainThread:#selector(executeThisCommand:) withObject:aCommand waitUntilDone:YES];
}
// this will throw
-(NSString *)executeCommand:(NSString *)command {
NSString *aCommand = [[[command stringByReplacingOccurrencesOfString:kOpenToken withString:#""]
stringByReplacingOccurrencesOfString:kCloseToken withString:#""]
stringByTrimmingLeadingAndTrailingWhitespaces];
if ([aCommand hasPrefix:#"="])
{
// variable. get value
[self getVariableFromCommand:aCommand];
}
else {
[self executeThisCommand:aCommand];
}
NSString *returnValue = [NSString stringWithString:processedCommand];
self.processedCommand = nil;
self.commandArguments = nil;
return returnValue;
}
-(void)executeThisCommand:(NSString *)aCommand {
BOOL hasError = NO;
// clear result
self.processedCommand = nil;
self.commandArguments = nil;
BOOL isFromJS = NO;
NSString *function = nil;
NSMutableArray *commandParts = nil;
#try {
// first, break the command into its parts and extract the function that needs to be called, and the (optional) arguments
commandParts = [[NSMutableArray alloc] initWithArray:[aCommand componentsSeparatedByString:#":"]];
if ([[[commandParts objectAtIndex:0] lowercaseString] isEqualToString:#"js-call"]) {
isFromJS = YES;
[commandParts removeObjectAtIndex:0];
}
// get our function, arguments
function = [[commandParts objectAtIndex:0] retain];
[commandParts removeObjectAtIndex:0];
if ([commandParts count] > 0){
if (isFromJS == YES) {
NSString *arguments = [[commandParts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([arguments length] > 0) {
self.commandArguments = [arguments JSONValue];
}
}
else {
self.commandArguments = [NSArray arrayWithArray:commandParts];
}
}
// build invoke
SEL sel = NSSelectorFromString(function);
if ([self respondsToSelector:sel]) {
[self performSelectorOnMainThread:sel withObject:nil waitUntilDone:YES];
// using invocation causes a SIGABORT because the try/catch block was not catching the exception.
// using perform selector fixed the problem (i.e., the try/catch block now correctly catches the exception, as expected)
}
else {
[appDelegate buildNewExceptionWithName:#"" andMessage:[NSString stringWithFormat:#"Object does not respond to selector %#", function]];
}
}
#catch (NSException * e) {
hasError = YES;
[self updateErrorMessage:[NSString stringWithFormat:#"Error processing command %#: %#", aCommand, [e reason]]];
}
#finally {
[function release];
[commandParts release];
}
if (hasError == YES) {
[appDelegate buildNewExceptionWithName:#"executeThisCommand" andMessage:self.errorMessage];
}
}
// this can return nil
-(NSString *)getQueryStringValue:(NSString *)name {
NSString *returnValue = nil;
if (queryString != nil) {
returnValue = [queryString objectForKey:[name lowercaseString]];
}
return returnValue;
}

How can I find calls to UIKit instances from a secondary thread?

My app is crashing in iOS 5 because I have some code that is calling UIKit instances from a secondary thread. You know you have this problem when you see the following error:
bool _WebTryThreadLock(bool), 0x811bf20: Multiple locks on web thread not allowed! Please file a bug. Crashing now…
So my question is what are some ways that I can find the code that is calling the UIKit instances from a secondary thread?
Here are some things I’ve tried already:
Commented out blocks that could be violating the rule
Added assert([NSThread isMainThread]) in places that might be processing in secondary thread
Added a symbolic breakpoint for _WebTryThreadLock
These things have helped me to find problem areas. However, in my final crash the _WebTryThreadLock breakpoint has no stack trace in any of the other threads. So, how I can find the code that causing the problem without a stack trace?
Thanks for your time!
Your assert() is probably the most valuable tool in this. I've been known to put a similar assertion at the beginning of every method in my Controller classes. If that doesn't find it, I add the assertion to my View classes. If that doesn't find it, I add it to any Model classes that I think are main-thread only.
To #craig's comment, the fact that it claims to be an internal bug might be accurate. But I think you're on the right path to closely examine your own code first.
I adapted the PSPDFUIKitMainThreadGuard.m to allow one to not have to worry about these things. Here: https://gist.github.com/k3zi/98ca835b15077d11dafc :
#import <objc/runtime.h>
#import <objc/message.h>
// Compile-time selector checks.
#define PROPERTY(propName) NSStringFromSelector(#selector(propName))
// A better assert. NSAssert is too runtime dependant, and assert() doesn't log.
// http://www.mikeash.com/pyblog/friday-qa-2013-05-03-proper-use-of-asserts.html
// Accepts both:
// - PSPDFAssert(x > 0);
// - PSPDFAssert(y > 3, #"Bad value for y");
#define PSPDFAssert(expression, ...) \
do { if(!(expression)) { \
NSLog(#"%#", [NSString stringWithFormat: #"Assertion failure: %s in %s on line %s:%d. %#", #expression, __PRETTY_FUNCTION__, __FILE__, __LINE__, [NSString stringWithFormat:#"" __VA_ARGS__]]); \
abort(); }} while(0)
///////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Helper for Swizzling
BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) {
PSPDFAssert(c && origSEL && newSEL && block);
Method origMethod = class_getInstanceMethod(c, origSEL);
const char *encoding = method_getTypeEncoding(origMethod);
// Add the new method.
IMP impl = imp_implementationWithBlock(block);
if (!class_addMethod(c, newSEL, impl, encoding)) {
NSLog(#"Failed to add method: %# on %#", NSStringFromSelector(newSEL), c);
return NO;
}else {
// Ensure the new selector has the same parameters as the existing selector.
Method newMethod = class_getInstanceMethod(c, newSEL);
PSPDFAssert(strcmp(method_getTypeEncoding(origMethod), method_getTypeEncoding(newMethod)) == 0, #"Encoding must be the same.");
// If original doesn't implement the method we want to swizzle, create it.
if (class_addMethod(c, origSEL, method_getImplementation(newMethod), encoding)) {
class_replaceMethod(c, newSEL, method_getImplementation(origMethod), encoding);
}else {
method_exchangeImplementations(origMethod, newMethod);
}
}
return YES;
}
// This installs a small guard that checks for the most common threading-errors in UIKit.
// This won't really slow down performance but still only is compiled in DEBUG versions of PSPDFKit.
// #note No private API is used here.
__attribute__((constructor)) static void PSPDFUIKitMainThreadGuard(void) {
#autoreleasepool {
for (NSString *selStr in #[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) {
SEL selector = NSSelectorFromString(selStr);
SEL newSelector = NSSelectorFromString([NSString stringWithFormat:#"pspdf_%#", selStr]);
if ([selStr hasSuffix:#":"]) {
PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self, CGRect r) {
if(!NSThread.isMainThread){
dispatch_async(dispatch_get_main_queue(), ^{
((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r);
});
}else{
((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r);
}
});
}else {
PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self) {
if(!NSThread.isMainThread){
dispatch_async(dispatch_get_main_queue(), ^{
((void ( *)(id, SEL))objc_msgSend)(_self, newSelector);
});
}else
((void ( *)(id, SEL))objc_msgSend)(_self, newSelector);
});
}
}
}
}
It automatically kicks calls into the main thread and thus you wouldn't even have to do anything but plop the code in.
This problem comes because you want to access to UI from secondary thread somehow, it can from webview of whatever else. It is not permitted because UIKit is not thread safe and can be accessed only from MainThread.
The very first thing you can do is to change your thread call to [self performSelectorOnMainThread:#selector(myMethod) withObject:nil waitUntilDone:NO]; (look for documentation).
In case when you have no other choice you can use GCD(Grand Central Dispathc)...
This code (just add to project and compile this file without ARC) causes assertions on UIKit access outside the main thread: https://gist.github.com/steipete/5664345
I've just used it to pickup numerous UIKit/main thread issues in some code I've just picked up.