Skip to content

Instantly share code, notes, and snippets.

@markd2
Created July 25, 2013 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markd2/6080126 to your computer and use it in GitHub Desktop.
Save markd2/6080126 to your computer and use it in GitHub Desktop.
Support file for Inside the Bracket, part 7, the final chapter, part two. This time, it's swizzling.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
// clang -g -fobjc-arc -Wall -framework Foundation -o swizzle swizzle.m
// Swap two methods
void SwizzleMethod (Class clas, SEL originalSelector, SEL newSelector) {
Method originalMethod =
class_getInstanceMethod (clas, originalSelector);
Method newMethod =
class_getInstanceMethod (clas, newSelector);
BOOL addedMethod =
class_addMethod (clas, originalSelector,
method_getImplementation(newMethod),
method_getTypeEncoding(newMethod));
if (addedMethod) {
class_replaceMethod (clas, newSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations (originalMethod, newMethod);
}
} // SwizzleMethod
// Naive implementation *sort* of works, but will clober the superclass if
// |clas| doesn't implement the original method but the super does.
// Don't use this. Really. It's used as an object lesson on being
// very careful with these tools.
void SwizzleMethodBadly (Class clas, SEL originalSelector, SEL newSelector) {
Method originalMethod = class_getInstanceMethod (clas, originalSelector);
Method newMethod = class_getInstanceMethod (clas, newSelector);
if (originalMethod && newMethod) {
method_exchangeImplementations (originalMethod, newMethod);
} else {
NSLog (@"no swizzle u!");
}
} // SwizzleMethodBadly
// --------------------------------------------------
// Say stuff from Cocoa or some library we want to hack
@interface BaseClass : NSObject
- (void) hornswoggle;
- (void) bamboozle;
- (void) doStuff; // Calls hornswoggle and bamboozle to do its work.
@end
@interface FirstBegat : BaseClass
// implements hornswoggle and bamboozle
@end
@interface SecondBegat : FirstBegat
// implements hornswoggle (not bamboozle)
@end
@implementation BaseClass
- (void) doStuff {
[self hornswoggle];
[self bamboozle];
} // doStuff
- (void) hornswoggle {
NSLog (@"BaseClass hornswoggle");
}
- (void) bamboozle {
NSLog (@"BaseClass bamboozle");
}
@end // BaseClass
@implementation FirstBegat
- (void) hornswoggle {
NSLog (@"FirstBegat hornswoggle calling");
[super hornswoggle];
}
- (void) bamboozle {
NSLog (@"FirstBegat bamboozle calling");
[super bamboozle];
}
@end // FirstBegat
@implementation SecondBegat
- (void) hornswoggle {
NSLog (@"SecondBegat hornswoggle calling");
[super hornswoggle];
}
@end // SecondBegat
// --------------------------------------------------
// Container for the various swizzled methods
@interface FirstBegat (HackNSlash)
+ (void) hck_hijackMethods;
@end
@implementation FirstBegat (HackNSlash)
+ (void) hck_hijackMethods {
SwizzleMethod ([self class], @selector(hornswoggle),
@selector($hackFirstBegat_Hornswoggle));
}
- (void) $hackFirstBegat_Hornswoggle {
NSLog (@"I'm in ur FirstBegat doin ur %s", sel_getName(_cmd));
[self $hackFirstBegat_Hornswoggle]; // Actually calls original implementation
}
@end
@interface SecondBegat (HackNSlash)
+ (void) hck_hijackMethods;
@end
@implementation SecondBegat (HackNSlash)
+ (void) hck_hijackMethods {
SwizzleMethodBadly ([self class], @selector(bamboozle),
@selector($hackSecondBegat_Bamboozle));
}
- (void) $hackSecondBegat_Bamboozle {
NSLog (@"I'm in ur SecondBegat doin ur %s", sel_getName(_cmd));
}
@end
int main (void) {
@autoreleasepool {
FirstBegat *first = [FirstBegat new];
SecondBegat *second = [SecondBegat new];
NSLog (@"--------------------------------------------------");
NSLog (@"FirstBegat, do stuff!");
[first doStuff];
NSLog (@"--------------------------------------------------");
NSLog (@"SecondBegat, do stuff!");
[second doStuff];
NSLog (@"==================================================");
[FirstBegat hck_hijackMethods];
NSLog (@"FirstBegat, do stuff!");
[first doStuff];
NSLog (@"--------------------------------------------------");
NSLog (@"SecondBegat, do stuff!");
[second doStuff];
NSLog (@"==================================================");
[SecondBegat hck_hijackMethods];
NSLog (@"FirstBegat, after bad swizzling, do stuff!");
[first doStuff];
NSLog (@"--------------------------------------------------");
NSLog (@"SecondBegat, do stuff!");
[second doStuff];
}
return 0;
} // main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment