articles icon indicating copy to clipboard operation
articles copied to clipboard

Method swizzling doesn't work properly in iOS 9

Open gerchicov-bp opened this issue 8 years ago • 4 comments

I tried code from your article: http://nshipster.com/method-swizzling/

But add iOS 9 (any 9.x except of simulator) and try to override @selector(presentViewController:animated:completion:) - it won't work.

gerchicov-bp avatar Nov 16 '15 14:11 gerchicov-bp

Hi @gerchicov-bp, thanks for getting in touch. Do you have a code sample that isn't working? And are you saying it works in the simulator, but not on the device?

natecook1000 avatar Nov 16 '15 16:11 natecook1000

@implementation UINavigationController (Extension)

- (void)swizzledPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
{
    [ self swizzledPresentViewController:viewControllerToPresent animated:flag completion:completion ];
}

#pragma mark -

+ (void)swizzle:(Class)class oldSelector:(SEL)old newSelector:(SEL)new
{
    Method oldMethod = class_getInstanceMethod(class, old);
    Method newMethod = class_getInstanceMethod(class, new);


    if(class_addMethod(class, old, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
    {
        class_replaceMethod(class, new, method_getImplementation(oldMethod), method_getTypeEncoding(oldMethod));
    }
    else
    {
        method_exchangeImplementations(oldMethod, newMethod);
    }
}

+ (void)load
{
    [self swizzle:UINavigationController.class oldSelector:@selector(presentViewController:animated:completion:) newSelector:@selector(swizzledPresentViewController:animated:completion:)];
}

@end

And somewhere on button click:

UIViewController *vc = [[UIViewController alloc] init];
[self.navigationController presentViewController:vc animated:YES completion:nil];

So this code must replace the original implementation with the same one. And yes, this code is called but then you get a crash with EXC_BAD_ACCESS which you can't handle with xcode exception breakpoint

gerchicov-bp avatar Nov 17 '15 06:11 gerchicov-bp

I also have found out that this bug is reproduced on very random devices (in my case it is iphone5 + ios9.0, but other users have newer devices and with iOS9.1).

gerchicov-bp avatar Nov 17 '15 08:11 gerchicov-bp

You may have to cast the result of a swizzled function if it returns a void or a primitive type. See the second footnote of https://blog.newrelic.com/2014/04/16/right-way-to-swizzle/, it saved me long nights tracking bugs. Not sure it is applicable in your case, but EXC_BAD_ACCESS on such a swizzled method makes me think it may have something to do with your code.

daladim avatar Jul 12 '16 23:07 daladim