How to swizzle a class method on iOS? How to swizzle a class method on iOS? ios ios

How to swizzle a class method on iOS?


Turns out, I wasn't far away. This implementation works for me:

void SwizzleClassMethod(Class c, SEL orig, SEL new) {    Method origMethod = class_getClassMethod(c, orig);    Method newMethod = class_getClassMethod(c, new);    c = object_getClass((id)c);    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));    else        method_exchangeImplementations(origMethod, newMethod);}


Objective-C swizzling using category

@interface cA : NSObject {}@end@implementation cA+(NSString*) cClassFooA {    return @"class fooA";}-(NSString*) cFooA {    return @"fooA";}@end@interface cB : NSObject {}@end@implementation cB+(NSString*) cClassFooB {    return @"class fooB";}-(NSString*) cFooB {    return @"fooB";}@end

NSObject+Swizzling.h

#import <Foundation/Foundation.h>@interface NSObject (Swizzling)+ (void)cExchangeClassWithCls1:(Class)cls1 Sel1:(SEL)sel1 Cls2:(Class)cls2 Sel2:(SEL)sel2;+ (void)cExchangeInstanceWithCls1:(Class)cls1 Sel1:(SEL)sel1 Cls2:(Class)cls2 Sel2:(SEL)sel2;@end

NSObject+Swizzling.m

#import "NSObject+Swizzling.h"#import <objc/runtime.h>@implementation NSObject (Swizzling)+ (void)cExchangeClassWithCls1:(Class)cls1 Sel1:(SEL)sel1 Cls2:(Class)cls2 Sel2:(SEL)sel2 {    Method originalMethod = class_getClassMethod(cls1, sel1);    Method swizzledMethod = class_getClassMethod(cls2, sel2);    method_exchangeImplementations(originalMethod, swizzledMethod);}+ (void)cExchangeInstanceWithCls1:(Class)cls1 Sel1:(SEL)sel1 Cls2:(Class)cls2 Sel2:(SEL)sel2 {    Method originalMethod = class_getInstanceMethod(cls1, sel1);    Method swizzledMethod = class_getInstanceMethod(cls2, sel2);    method_exchangeImplementations(originalMethod, swizzledMethod);}@end

using via Objective-C

- (void)testCExchangeClass {    [NSObject cExchangeClassWithCls1:[cA class] Sel1:@selector(cClassFooA) Cls2:[cB class] Sel2:@selector(cClassFooB)];    XCTAssertEqual(@"class fooB", [cA cClassFooA]);}- (void)testCExchangeInstance {    [NSObject cExchangeInstanceWithCls1:[cA class] Sel1:@selector(cFooA) Cls2:[cB class] Sel2:@selector(cFooB)];    XCTAssertEqual(@"fooB", [[[cA alloc] init] cFooA]);}

[Add Swift as an consumer]

using via Swift

func testCExchangeClass() {    NSObject.cExchangeClass(withCls1: sA.self, sel1: #selector(sA.sClassFooA), cls2: sB.self, sel2: #selector(sB.sClassFooB))    XCTAssertEqual("class fooB", sA.sClassFooA())}func testCExchangeInstance() {    NSObject.cExchangeInstance(withCls1: sA.self, sel1: #selector(sA.sFooA), cls2: sB.self, sel2: #selector(sB.sFooB))    XCTAssertEqual("fooB", sA().sFooA())}

[Swift swizzling]