72
Changing the Rules of the Game Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com

Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

  • Upload
    others

  • View
    46

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Changing the Rulesof the Game

Objective-C Runtime Manipulation

Whitney Young FadingRed

@wbyoungwbyoung.github.com

Page 2: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Runtime API86 public, open source C functions

Page 3: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Runtime API

• Classes

• Methods

• Objects

• Properties & instance variables

• Selectors

• Protocols

Page 4: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

ExampleSimplifying Core Data Query Syntax

Page 5: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Ruby on Rails

@articles = Article. where(:created_at => start_date..end_date). order('created_at')

Page 6: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Django

self.articles = Article.objects. filter(created__gte=start_date, created__lte=end_date). order_by('created')

Page 7: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Core DataNSEntityDescription *entity = [NSEntityDescription entityForName:@"Article" inManagedObjectContext:context];NSFetchRequest *request = [[NSFetchRequest alloc] init];[request setEntity:entity];[request setPredicate: [NSPredicate predicateWithFormat:@"created >= %@ && created <= %@", startDate, endDate]];[request setSortDescriptors: @[[NSSortDescriptor sortDescriptorWithKey:@"created" ascending:YES]]];NSError *error = nil;self.articles = [context executeFetchRequest:request error:&error];

Page 8: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Core Data + Runtime

self.articles = context.query.articles[@{! @"created__gte": startDate,! @"created__lte": endDate }][@"^created"];

Page 9: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation Goals

• Easy to read and use

• Little to no code overhead for use

• Delayed evaluation

• Cheap copies of query objects

• Good runtime examples

Page 10: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation Plan

• Query operations always return a copy

• Query objects are array proxies

• Evaluate on first use only

• Queries can be bound (or unbound)

• Knows the entity it’s trying to fetch

Page 11: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Core Data + Runtime

self.articles = context.query.articles[@{! @"created__gte": startDate,! @"created__lte": endDate }][@"^created"];

Page 12: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation I

• Make query work like an array

[query objectAtIndex:0];

What we need

• Message forwarding

• Proxy objects

Page 13: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Message Sending

[array objectAtIndex:0];

Page 14: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Message Sending

objc_msgSend( array, @selector(objectAtIndex:), 0);

[array objectAtIndex:0];

Page 15: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Message Sending

• Search the class’s method cache for the IMP

• If not found, search the class hierarchy for the IMP

• Jump to IMP if found (jmp assembly instruction)

• If not found, jump to _objc_msgforward

• All objects can forward messages they don’t respond to

Page 16: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Message Forwarding

- (void)forwardInvocation:(NSInvocation *)invocation { [invocation setTarget:_realArray]; [invocation invoke];}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { return [_realArray methodSignatureForSelector:sel];}

Page 17: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Message Forwarding

• Other Options

- (id)forwardingTargetForSelector:(SEL)name

+ (BOOL)resolveClassMethod:(SEL)name

+ (BOOL)resolveInstanceMethod:(SEL)name

Page 18: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

NSProxy

• Designed for use with message forwarding

• Root class

• Implements minimal number of methods

• Used frequently throughout Cocoa

Page 19: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation I

• Make query work like an array

[query objectAtIndex:0];

Demo

Page 20: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation II

• Return unbound query from managed object context

[context query]

What we need

• Associated objects

Page 21: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Associated Objects

• Arbitrary key/value storage for any object

static void *kSomeKey = &(void *){0};objc_setAssociatedObject(obj, kSomeKey, val, OBJC_ASSOCIATION_RETAIN);objc_getAssociatedObject(obj, kSomeKey);

Page 22: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation II

• Return unbound query from managed object context

[context query]

Demo

Page 23: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation III

• Resolve binding methods dynamically

[context.query people]

What we need

• Message forwarding

• Adding methods to classes

Page 24: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Adding Methods

BOOL class_addMethod(Class class, SEL name, IMP imp, const char *types)

• IMP is simply a C function

• Type encoding

• Defines the return & argument types

• Best retrieved from another method

Page 25: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Adding Methodsvoid MyRuntimeMethod(id self, SEL _cmd, NSString *arg) { // implementation}

Method prototype = class_getInstanceMethod([NSString class], @selector(appendString:));char *types = method_getTypeEncoding(prototype);

class_addMethod([MyClass class], @selector(myNewMethod:), (IMP)MyRuntimeMethod, types);

Page 26: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation III

• Resolve binding methods dynamically

[context.query people]

Demo

Page 27: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation IV

• Implementing binding method

[context.query people]

What we need

• Nothing new :)

Demo

Page 28: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation IV

• Pluralization

[context.query people]

Goal

• Pluralize simple words automatically

• Allow simple override by each model class

Page 29: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Override Example

@implementation FRPerson

+ (NSString *)pluralizePerson { return @"people";}

@end

Page 30: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation IV

• Pluralization

[context.query people]

What we need

• Selector names from strings

• Performing selectors

Page 31: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Selectors

• Really just unique C strings

SEL sel_getUid(const char *str)SEL NSSelectorFromString(NSString *string)

const char *sel_getName(SEL selector)NSString *NSStringFromSelector(SEL selector)

Page 32: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Performing Selectors

[object performSelector:selector];

[object performSelector:selector withObject:arg1 withObject:arg2];

Page 33: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Performing Selectors ARC

IMP imp = [object methodForSelector:sel];void (*func)(id,SEL,CGRect,CGFloat) = (void *)imp;

func(object, sel, rect, float);

Page 34: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Performing Selectors ARC

Class class = [object class];IMP imp = class_getMethodImplementation(class, sel);void (*func)(id,SEL,CGRect,CGFloat) = (void *)imp;

func(object, sel, rect, float);

Page 35: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation IV

• Pluralization

[context.query people]

Demo

Page 36: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation V

• Keyed subscript & other query operations

context.query.people[@"name = 'Whitney'"]

What we need

• No runtime needed

Explore the code

Page 37: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

ExampleMixins

Page 38: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Ruby: Modules

class Article < Object! attr_accessor :created_atendmodule TimeAgo! def time_ago # more code would go in here! ! seconds = Time.now - self.created_at! ! "#{seconds.to_i / 3600} hours ago"! endend

Page 39: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Ruby: Class Mixin

class Article! include TimeAgoend

a = Article.newa.created_at = Time.now - 3600 * 3a.time_ago # "3 hours ago"

Page 40: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Ruby: Instance Mixin

a = Article.newa.created_at = Time.now - 3600 * 3a.extend TimeAgoa.time_ago # "3 hours ago"

Page 41: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Objective-C: Modules

@interface FRTimeAgo : FRModule@end

@implementation FRTimeAgo- (NSString *)timeAgo { // more code would go in here NSTimeInterval seconds = -[self.creationDate timeIntervalSinceNow]; return [NSString stringWithFormat:@"%i hours ago", seconds / 3600];}

@end

Page 42: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Objective-C: Class Mixins

[FRTimeAgo extendClass:[FRArticle class]];

FRArticle *a = [[FRArticle alloc] init];a.creationDate = [NSDate dateWithTimeIntervalSinceNow:-3600*3];[(id)a timeAgo]; // @"3 hours ago"

Page 43: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Objective-C: Instance Mixins

FRArticle *a = [[FRArticle alloc] init];a.creationDate = [NSDate dateWithTimeIntervalSinceNow:-3600*3];[FRTimeAgo extendInstance:a];[(id)a timeAgo]; // @"3 hours ago"

Page 44: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation I

• Class Mixins

[FRTimeAgo extendClass:[FRArticle class]];

What we need

• Method enumeration

• Replacing methods on classes

Page 45: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Method Enumeration

• Copy methods from module to destination class

Method *class_copyMethodList(Class cls, unsigned int *outCount)

• Returns methods from just that class

• Allocated memory must be freed

Page 46: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Replacing Methods

IMP class_replaceMethod(Class class, SEL name, IMP imp, const char *types)

• Similar to class_addMethod

• Adds or replaces method

• Returns IMP if method was replaced

Page 47: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation I

• Class Mixins

[FRTimeAgo extendClass:[FRArticle class]];

Demo

Page 48: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation II

• Instance Mixins

[FRTimeAgo extendInstance:a];

What we need

• Dynamic subclassing

• Changing object class

Page 49: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Dynamic Subclassing

• Why create a dynamic subclass?

• Subclass won’t affect instances of main class

• We can safely change the object’s class to this class

• Apple does this with KVO

Page 50: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Let’s step backObjects & Classes

Page 51: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?

a dog

isanameowner

...age

Page 52: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?instance

an animal

a dog

Page 53: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?class

NSObject

Animal

Dog

instance

an animal

a dog

Page 54: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?class

NSObject

Animal

Dog

instance

an animal

a dog

Page 55: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?class

NSObject

Animal

Dog

instance

an animal

a dog

Page 56: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?class

NSObject

Animal

Dog

instance

an animal

a dog

Page 57: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?

NSObject

class metaclass

NSObject

Animal

Dog

Animal

Dog

instance

an animal

a dog

Page 58: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?

NSObject

class metaclass

NSObject

Animal

Dog

Animal

Dog

instance

an animal

a dog

Page 59: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

What are Objects?

NSObject

class metaclass

NSObject

Animal

Dog

Animal

Dog

instance

an animal

a dog

Page 60: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Dynamic Subclassing

• Create dynamic subclass to handle instance mixins

Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)void objc_registerClassPair(Class class)

• Changing an object’s class

object_setClass(id obj, Class class)

Page 61: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation II

• Instance Mixins

[FRTimeAgo extendInstance:a];

Demo

Page 62: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Implementation III

• Calling original implementation

• Like calling super, but from the module

What we need

• Nothing new :)

Thought exercise

Page 63: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Other TechniquesStandard Runtime Uses

Page 64: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Replacing Methods

Goals

• Replace method

• Be able to call original method

a.k.a. Method Swizzling

Page 65: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Replacing Methods

• Store the original IMP to call later

class_getInstanceMethod

method_getImplementation

• Replacing the method is simple

class_replaceMethod

Page 66: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Replacing Methods

void (*OrigDrawRect)(id, SEL, NSRect);void MyDrawRect(id self, SEL cmd, NSRect rect) { if ([[self title] isEqualToString:@"OK"]) { // draw custom okay buttons } else { OrigDrawRect(self, _cmd, rect); }}

Page 67: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Replacing Methods

@implementation NSButton (ButtonDrawing)+ (void)load { [self swizzle:@selector(drawRect:) with:(IMP)MyDrawRect store:(IMPPointer)&OrigDrawRect];}@end

Page 68: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Replacing Methodstypedef IMP *IMPPointer;

BOOL class_swizzleMethodAndStore(Class class, SEL original, IMP replacement, IMPPointer store) { IMP imp = NULL; Method method = class_getInstanceMethod(class, original); if (method) { const char *type = method_getTypeEncoding(method); imp = class_replaceMethod(class, original, replacement, type); if (!imp) { imp = method_getImplementation(method); } } if (imp && store) { *store = imp; } return (imp != NULL);}

@implementation NSObject (FRRuntimeAdditions)+ (BOOL)swizzle:(SEL)original with:(IMP)replacement store:(IMPPointer)store { return class_swizzleMethodAndStore(self, original, replacement, store);}@end

Page 70: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Bypassing Message Sending

SEL selector = @selector(setFilled:);void (*setter)(id, SEL, BOOL) = (void *)[target methodForSelector:selector];for (int i = 0; i < 1000; i++) setter(targetList[i], selector, YES);

You’ll probably never need to do this!

Page 71: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Be CreativeThe sky’s the limit!

Page 72: Objective-C Runtime Manipulation - GitHub Pageswbyoung.github.io/objective_c_runtime.pdf · Objective-C Runtime Manipulation Whitney Young FadingRed @wbyoung wbyoung.github.com. Runtime

Thank you!Questions?

Whitney Young FadingRed

@wbyoungwbyoung.github.com