Skip to content

Instantly share code, notes, and snippets.

@markd2
Created July 25, 2013 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save markd2/6080158 to your computer and use it in GitHub Desktop.
Save markd2/6080158 to your computer and use it in GitHub Desktop.
Support file for Inside the Bracket part 7, adding some methods to classes at runtime.
// Add some methods with the runtime.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
// clang -g -fobjc-arc -Wall -framework Foundation -o addstuff addstuff.m
@interface Glorn : NSObject
@end
@implementation Glorn
+ (BOOL) resolveInstanceMethod: (SEL) selector {
// Refuse this one so we get the "nobody here" exception.
if (sel_isEqual(selector, @selector(larvoid))) return NO;
// Don't want to handle anything that takes arguments.
if (strchr(sel_getName(selector), ':')) return NO;
IMP blockImp =
imp_implementationWithBlock ((__bridge void *) ^(id self) {
NSLog (@"you just called %@",
NSStringFromSelector(selector));
});
class_addMethod ([self class], selector, blockImp, "v@:");
return YES;
} // resolveInstanceMethod
@end
@interface Glorn (HushTheCompiler)
- (NSString *) larvoid;
- (NSString *) greetingWithCount: (NSUInteger) count;
- (void) keep;
- (void) watching;
- (void) theSkies;
@end
static NSString *Larvoid (id self, SEL _cmd) {
return @"Zogg";
} // Larvoid
void AddSomeMethods (void) {
Glorn *glorn = [Glorn new];
NSString *name;
// See that it breaks;
@try {
name = [glorn larvoid];
}
@catch (id thing) {
NSLog (@"got expected exception");
}
// Add a method with a function pointer
Class glornClass = [Glorn class];
BOOL success = class_addMethod (glornClass, @selector(larvoid), (IMP)Larvoid, "@:v");
if (!success) {
printf ("phooey, couldn't add method\n");
return;
}
name = [glorn larvoid];
NSLog (@"Hello my name is %@", name);
// Add a method with a block
IMP blockImp =
imp_implementationWithBlock ((__bridge void *)
^(id self, NSUInteger count) {
for (NSUInteger i = 0; i < count; i++) {
NSLog (@"Hello #%ld, %@", i, name);
}
});
char *encoding;
asprintf(&encoding, "v@:%s", @encode(NSUInteger));
success = class_addMethod (glornClass, @selector(greetingWithCount:),
blockImp, encoding);
free (encoding);
if (!success) {
printf ("lame, couldn't add the block imp\n");
return;
}
[glorn greetingWithCount: 5];
[glorn keep];
[glorn watching];
[glorn theSkies];
} // AddSomeMethods
int main (void) {
@autoreleasepool {
AddSomeMethods ();
}
return 0;
} // void
#if 0
-[Glorn larvoid]: unrecognized selector sent to instance 0x1050142b0
got expected exception
Hello my name is Zogg
Hello #0, Zogg
Hello #1, Zogg
Hello #2, Zogg
Hello #3, Zogg
Hello #4, Zogg
you just called who
you just called goes
you just called there
you just called _doZombieMe
(_doZombieMe was totally unexpected)
#0 +[Glorn resolveInstanceMethod:] (self=0x100003518, _cmd=0x7fff8cf433d3, selector=0x7fff8b59ec3c) at addstuff.m:23
#1 0x00007fff8a38db9b in _class_resolveMethod ()
#2 0x00007fff8a38b35e in lookUpMethod ()
#3 0x00007fff8a38da5c in class_respondsToSelector ()
#4 0x00007fff8b44d051 in -[NSObject dealloc] ()
#5 0x00000001000016f6 in AddSomeMethods () at addstuff.m:93
#6 0x000000010000189d in main () at addstuff.m:100
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment