steipete / Aspects

Delightful, simple library for aspect oriented programming in Objective-C and Swift.

Home Page:https://twitter.com/steipete

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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?