Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

147 lines (120 sloc) 2.979 kb
#import "NSObject+SPInvocationGrabbing.h"
#import <execinfo.h>
#pragma mark Invocation grabbing
@interface SPInvocationGrabber ()
@property (readwrite, retain, nonatomic) id object;
@property (readwrite, retain, nonatomic) NSInvocation *invocation;
@end
@implementation SPInvocationGrabber
@synthesize object = _object;
@synthesize invocation = _invocation;
@synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone;
- (id)initWithObject:(id)obj
{
return [self initWithObject:obj stacktraceSaving:NO];
}
- (id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack
{
if ((self = [super init]) != nil) {
_object = [obj retain];
if (saveStack) {
[self saveBacktrace];
}
}
return self;
}
- (void)dealloc
{
free(frameStrings);
[_object release];
[_invocation release];
[super dealloc];
}
- (void)runInBackground
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@try {
[self invoke];
}
@finally {
[pool drain];
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation retainArguments];
anInvocation.target = _object;
self.invocation = anInvocation;
if (backgroundAfterForward) {
[NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil];
} else if (onMainAfterForward) {
[self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector
{
NSMethodSignature *signature = [super methodSignatureForSelector:inSelector];
if (signature == NULL) {
signature = [_object methodSignatureForSelector:inSelector];
}
return signature;
}
- (void)invoke
{
@try {
[_invocation invoke];
}
@catch (NSException * e) {
NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e);
[self printBacktrace];
printf("\n");
[e raise];
}
self.invocation = nil;
self.object = nil;
}
- (void)saveBacktrace
{
void *backtraceFrames[128];
frameCount = backtrace(&backtraceFrames[0], 128);
frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount);
}
- (void)printBacktrace
{
for (int x = 3; x < frameCount; x++) {
if (frameStrings[x] == NULL) {
break;
}
printf("%s\n", frameStrings[x]);
}
}
@end
@implementation NSObject (SPInvocationGrabbing)
- (id)grab
{
return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease];
}
- (id)invokeAfter:(NSTimeInterval)delta
{
id grabber = [self grab];
[NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO];
return grabber;
}
- (id)nextRunloop
{
return [self invokeAfter:0];
}
- (id)inBackground
{
SPInvocationGrabber *grabber = [self grab];
grabber.backgroundAfterForward = YES;
return grabber;
}
- (id)onMainAsync:(BOOL)async
{
SPInvocationGrabber *grabber = [self grab];
grabber.onMainAfterForward = YES;
grabber.waitUntilDone = !async;
return grabber;
}
@end
Jump to Line
Something went wrong with that request. Please try again.