Infinite Loop when overriding a method at two points which includes a call to super
davedelong opened this issue · comments
This will infinitely loop:
@interface A : NSObject
- (void)foo;
@end
@implementation A
- (void)foo {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
@end
@interface B : A @end
@implementation B
- (void)foo {
NSLog(@"%s", __PRETTY_FUNCTION__);
[super foo];
}
@end
int main(int argc, char *argv[]) {
[B aspect_hookSelector:@selector(foo) atPosition:AspectPositionBefore withBlock:^(id object, NSArray *arguments) {
NSLog(@"before -[B foo]");
}];
[A aspect_hookSelector:@selector(foo) atPosition:AspectPositionBefore withBlock:^(id object, NSArray *arguments) {
NSLog(@"before -[A foo]");
}];
B *b = [[B alloc] init];
[b foo];
}
Thanks for the report Dave! I might just opt for blocking this for the first version, don't see a way to get the IMP out of the NSInvocation. (https://twitter.com/davedelong/status/462834335528124417)
For future reference. We now keep track of what has been modified and simply disallow hooking into the same method within a subclass hierarchy. In the above example, hook B will work, and hook A will return nil. If you reverse, hook A will work, and hook B will return nil.
Now we could solve this so both work, but this would require going down to assembly and writing a version for each platform.
I have a hard time following this... can somebody explain in 5 bullets what's going on here?
Why doesn't A's foo get called?