lombax85 / FLCodeInjector

With this class you can inject code (using method swizzling) in Objective C methods in a very easy way. Useful for debug
MIT License
10 stars 1 forks source link

Suggestion about swizzling method like touchesBegan #2

Open bestswifter opened 7 years ago

bestswifter commented 7 years ago

Inspired from this blog: The Right Way to Swizzle in Objective-C

I met the same problem when trying to swizzle touchesBegan method of UIView. My solution is using IMP directly.

static IMP __original_TouchesBegan_Method_Imp;

+ (void)load {
    Method touchesBegan = class_getInstanceMethod([UIView class], @selector(touchesBegan:withEvent:));
    Method yoga_touchesBegan = class_getInstanceMethod([UIView class], @selector(yoga_touchesBegan:withEvent:));
    __original_TouchesBegan_Method_Imp = method_getImplementation(touchesBegan);

    method_exchangeImplementations(touchesBegan, yoga_touchesBegan);
}
- (void)yoga_touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touches Ended, self = %@", self);
    if ([NSStringFromClass([self class]) hasPrefix:@"Yoga"]) {
          // Your logic here
    }
    else {
        void (*functionPointer)(id, SEL, NSSet<UITouch *> *, UIEvent *) = (void (*)(id, SEL, NSSet<UITouch *> *, UIEvent *))__original_TouchesEnded_Method_Imp;
        functionPointer(self, _cmd, touches, event);
    }
}
sghiassy commented 6 years ago

Nice! Thx for the post. I ended up with the following category based on your approach.

static IMP __original_TouchesBegan_Method_Imp;

@implementation UIView (Touch)

+ (void)load {
    Method touchesBegan = class_getInstanceMethod([UIView class], @selector(touchesBegan:withEvent:));
    Method xxx_touchesBegan = class_getInstanceMethod([UIView class], @selector(xxx_touchesBegan:withEvent:));
    __original_TouchesBegan_Method_Imp = method_getImplementation(touchesBegan);
    method_exchangeImplementations(touchesBegan, xxx_touchesBegan);
}

- (void)xxx_touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    void (*functionPointer)(id, SEL, NSSet<UITouch *> *, UIEvent *) = (void (*)(id, SEL, NSSet<UITouch *> *, UIEvent *))__original_TouchesBegan_Method_Imp;
    functionPointer(self, _cmd, touches, event);
    // Your logic here
}

@end