views:

152

answers:

2

I'm trying to debug some touchesBegan/Moved/Ended related slowdown in my game; I think that some of my touch responders are not unloading properly, and so as the game runs on more and more of them stack up and the touches get less responsive because they have to pass through a larger and larger responder chain.

Is there some way to view/retrieve the path taken by a UITouch as it moves through the chain? Or simply some way to retrieve a list of all active responders?

Thanks, -S

+1  A: 

I would look into your memory usage, rather than trying to retrieve all the responders. Either look into instruments http://www.mobileorchard.com/find-iphone-memory-leaks-a-leaks-tool-tutorial/ or conversely, just throw in a few NSLog(@"responded"); into your touchesBegan methods and see if it gets logged like ten times for each touch.

Kenny Winker
+3  A: 

You can hijack the desired methods on UIResponder to add logging and then call the original method. Here's an example:

#import <Foundation/NSObjCRuntime.h>

@interface UIResponder (MYHijack)
+ (void)hijack;
@end

@implementation UIResponder (MYHijack)
+ (void)hijackSelector:(SEL)originalSelector withSelector:(SEL)newSelector
{
    Class class = [UIResponder class];
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method categoryMethod = class_getInstanceMethod(class, newSelector);
    method_exchangeImplementations(originalMethod, categoryMethod);
}

+ (void)hijack
{
    [self hijackSelector:@selector(touchesBegan:withEvent:) withSelector:@selector(MYHijack_touchesBegan:withEvent:)];
}

- (void)MYHijack_touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touches!");
    [self MYHijack_touchesBegan:touches withEvent:event]; // Calls the original version of this method
}
@end

Then somewhere in your app (I sometimes put it in main() itself), just call [UIResponder hijack]. As long as the UIResponder subclass calls super at some point, your code will be injected.

method_exchangeImplementations() is a beautiful thing. Be careful with it of course; it's great for debugging, but very confusing if used indiscriminately.

Rob Napier
`NSNotificationCenter` → `self`?
zoul
@zoul. Sorry, this code came from a hijack of NSNotificationCenter. Good catch. Fixed.
Rob Napier
@Rob: This doesn't seem to compile for iOS 3.2. Claims that _Method_ doesn't exist (and the other reflection functions you use as well). Any idea why?
Aviad Ben Dov
Make sure to #import <Foundation/NSObjCRuntime.h>. I'll edit the answer to include that.
Rob Napier