1
#import "NSObject+SPInvocationGrabbing.h"
4
#pragma mark Invocation grabbing
5
@interface SPInvocationGrabber ()
6
@property (readwrite, retain, nonatomic) id object;
7
@property (readwrite, retain, nonatomic) NSInvocation *invocation;
11
@implementation SPInvocationGrabber
12
- (id)initWithObject:(id)obj;
14
return [self initWithObject:obj stacktraceSaving:YES];
17
-(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack;
30
self.invocation = nil;
33
@synthesize invocation = _invocation, object = _object;
35
@synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone;
36
- (void)runInBackground;
38
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
48
- (void)forwardInvocation:(NSInvocation *)anInvocation {
49
[anInvocation retainArguments];
50
anInvocation.target = _object;
51
self.invocation = anInvocation;
53
if(backgroundAfterForward)
54
[NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil];
55
else if(onMainAfterForward)
56
[self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone];
58
- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector {
59
NSMethodSignature *signature = [super methodSignatureForSelector:inSelector];
60
if (signature == NULL)
61
signature = [_object methodSignatureForSelector:inSelector];
72
@catch (NSException * e) {
73
NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e);
74
[self printBacktrace];
79
self.invocation = nil;
85
void *backtraceFrames[128];
86
frameCount = backtrace(&backtraceFrames[0], 128);
87
frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount);
89
-(void)printBacktrace;
92
for(x = 3; x < frameCount; x++) {
93
if(frameStrings[x] == NULL) { break; }
94
printf("%s\n", frameStrings[x]);
99
@implementation NSObject (SPInvocationGrabbing)
102
return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease];
104
-(id)invokeAfter:(NSTimeInterval)delta;
106
id grabber = [self grab];
107
[NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO];
112
return [self invokeAfter:0];
116
SPInvocationGrabber *grabber = [self grab];
117
grabber.backgroundAfterForward = YES;
120
-(id)onMainAsync:(BOOL)async;
122
SPInvocationGrabber *grabber = [self grab];
123
grabber.onMainAfterForward = YES;
124
grabber.waitUntilDone = !async;