SlideShare ist ein Scribd-Unternehmen logo
1 von 22
The Objective-c Runtime
Павел Альбицкий
p.albitsky@gmail.com
Open source
libobjc.dylib
http://www.opensource.apple.com/source/objc
4/objc4-680/
Functions
class_getName
class_getSuperclass
class_setSuperclass
class_isMetaClass
class_getInstanceSize
class_getInstanceVariable
class_getClassVariable
class_addIvar
class_copyIvarList
class_getIvarLayout
class_setIvarLayout
class_getWeakIvarLayout
class_setWeakIvarLayout
class_getProperty
class_copyPropertyList
class_addMethod
class_getInstanceMethod
class_getClassMethod
class_copyMethodList
class_replaceMethod
class_getMethodImplementation
class_getMethodImplementation_stret
class_respondsToSelector
class_addProtocol
class_addProperty
class_replaceProperty
class_conformsToProtocol
class_copyProtocolList
class_getVersion
class_setVersion
objc_getFutureClass
objc_setFutureClass
Working with Classes
Adding Classes
objc_allocateClassPair
objc_disposeClassPair
objc_registerClassPair
objc_duplicateClass
Instantiating Classes
class_createInstance
objc_constructInstance
objc_destructInstance
Working with Instances
object_copy
object_dispose
object_setInstanceVariable
object_getInstanceVariable
object_getIndexedIvars
object_getIvar
object_setIvar
object_getClassName
object_getClass
object_setClass
Obtaining Class Definitions
objc_getClassList
objc_copyClassList
objc_lookUpClass
objc_getClass
objc_getRequiredClass
objc_getMetaClass
Working with Instance Variables
ivar_getName
ivar_getTypeEncoding
ivar_getOffset
Associative References
objc_setAssociatedObject
objc_getAssociatedObject
objc_removeAssociatedObjects
NSObject.mm
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)respondsToSelector:(SEL)sel {
if (!sel) return NO;
return class_respondsToSelector_inst([self class], sel, self);
}
- (BOOL)conformsToProtocol:(Protocol *)protocol {
if (!protocol) return NO;
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (class_conformsToProtocol(tcls, protocol)) return YES;
}
return NO;
}
- (id)performSelector:(SEL)sel {
if (!sel) [self doesNotRecognizeSelector:sel];
return ((id(*)(id, SEL))objc_msgSend)(self, sel);
}
NSObject
@interface NSObject <NSObject> {
Class isa;
}
typedef struct objc_class *Class;
struct objc_class {
Class isa;
#if !__OBJC2__
Class super_class
const char *name
long version
long info
long instance_size
struct objc_ivar_list *ivars
struct objc_method_list **methodLists
struct objc_cache *cache
struct objc_protocol_list *protocols
#endif
};
NSObject
typedef struct objc_object *id;
typedef struct objc_selector *SEL;
typedef struct objc_method *Method;
typedef struct objc_ivar *Ivar;
typedef struct objc_category *Category;
typedef struct objc_property *objc_property_t;
typedef struct objc_object Protocol;
Class hierarchy
@interface BaseExample : NSObject {
NSString *_ivarBase;
}
@property(nonatomic, strong) NSString *baseProperty;
- (void)test;
+ (NSString *)baseClassMethod;
@end
#import "BaseExample.h"
@interface Example : BaseExample {
NSString *_ivarExample;
}
@property(nonatomic, strong) NSString *exampleProperty;
- (void)test;
- (NSString *)execWithParam:(NSString *)param;
+ (NSString *)exampleClassMethod;
@end
Instance of Example Class Example Metaclass Example
isa isa
Class BaseExample
isa
Class NSObject
isa
Metaclass
BaseExample
Metaclass NSObject
super_class
super_class
super_class
super_class
Class hierarchy
struct objc_method {
SEL method_name; // signature of method
char *method_types; // types of the parameters to the method
IMP method_imp; // memory address of the start of code block
};
typedef struct objc_method *Method;
A selector is the name used to select a method to execute for an object, or the
unique identifier that replaces the name when the source code is compiled.
Selector – C-string;
IMP - typedef id (*IMP)(id self,SEL _cmd,...);
Method
NSString *result = [example execWithParam:@"param"];
id objc_msgSend(id self, SEL op, ...)
result = objc_msgSend(example, @selector(execWithParam:), @"param");
Tail-call: typedef id (*IMP)(id self,SEL _cmd,...);
void objc_msgSend(void /* id self, SEL op, ... */ )
NSString *result = ((NSString* (*)(id, SEL, NSString *))objc_msgSend)(example,
@selector(execWithParam:), @"param");
Sending Messages
id objc_msgSend(id self, SEL op, ...)
Sends a message with a simple return value to an instance of a class.
double objc_msgSend_fpret(id self, SEL op, ...)
Sends a message with a floating-point return value to an instance of a class.
void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...)
Sends a message with a data-structure return value to an instance of a class.
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
Sends a message with a simple return value to the superclass of an instance of a class.
void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...) Sends a message with a
data-structure return value to the superclass of an instance of a class.
objc_msgSend
Message forwarding
resolveInstanceMethod
forwardingTargetForSelector
forwardInvocation
Message handled
Message
not handled
Return NO
Return YES
Return nil
Return
replacement
receiver
resolveInstanceMethod
1. Class cache -> class dispatch table -> all super classes
2. resolveInstanceMethod for @dynamic properties
id dynamicGetter(id self, SEL _cmd);
void dynamicSetter(id self, SEL _cmd, id value);
+ (BOOL)isDynamicProperty:(NSString *)selectorString;
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSString *selectorString = NSStringFromSelector(sel);
if ([self isDynamicProperty:selectorString]) {
if ([selectorString hasPrefix:@"set"]) {
class_addMethod(self, sel, (IMP)dynamicSetter, "v@:@");
} else {
class_addMethod(sel, sel, (IMP)dynamicGetter, "@@:");
}
return YES;
}
return [super resolveInstanceMethod:sel];
}
// "v@:@", "@@:" - Objective-C type encodings
forwardingTargetForSelector
3. The Runtime then calls forwardingTargetForSelector
Returns the object to which unrecognized messages should first be directed.
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(magicMethod:)) {
return magicObject;
} else {
return [super forwardingTargetForSelector:aSelector];
}
}
forwardInvocation
@implementation InvClass
- (NSString *)invWithFirst:(NSString *)first second:(NSNumber *)second
third:(NSArray *)third {
return [NSString stringWithFormat:@"first: %@, second: %@, third: %@", first, second,
third];
}
@end
// perform unrecognized selector
Example *example = [Example new];
SEL selector = @selector(invWithFirst:);
NSString *result = [example performSelector:selector
withObject:@"first"];
forwardInvocation
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(invWithFirst:)) {
return NO;
}
return YES;
}
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(invWithFirst:)) {
return nil;
}
return [super forwardingTargetForSelector:aSelector];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
SEL customSelector = @selector(invWithFirst:second:third:);
signature = [_invObject methodSignatureForSelector:customSelector];
}
return signature;
}
forwardInvocation
- (void)forwardInvocation:(NSInvocation *)anInvocation {
SEL selector = anInvocation.selector;
if ([_invObject respondsToSelector:selector]) {
[anInvocation setTarget:_invObject];
SEL customSelector = @selector(invWithFirst:second:third:);
[anInvocation setSelector:customSelector];
NSString *first = @"first";
NSNumber *second = @2;
NSArray *third = @[@”3", @”33”, @”333"];
[anInvocation setArgument:&first atIndex:2];
[anInvocation setArgument:&second atIndex:3];
[anInvocation setArgument:&third atIndex:4];
[anInvocation invoke];
} else {
[self doesNotRecognizeSelector:selector];
}
}
Method Swizzling
#import <objc/runtime.h>
@import Crashlytics;
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(swizzled_viewWillAppear:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)swizzled_viewWillAppear:(BOOL)animated {
CLS_LOG(@"CLSLOG viewWillAppear: %@", self);
[self swizzled_viewWillAppear:animated];
}
@end
URLs
• Mike Ash
• Objective-C Runtime Reference
• Objective-C Runtime Programming Guide
• opensource.apple.com
Спасибо за внимание!
Павел Альбицкий
p.albitsky@gmail.com

Weitere ähnliche Inhalte

Was ist angesagt?

Javascript Basics
Javascript BasicsJavascript Basics
Javascript Basicsmsemenistyi
 
Introduction to Clean Code
Introduction to Clean CodeIntroduction to Clean Code
Introduction to Clean CodeJulio Martinez
 
Intro to Javascript
Intro to JavascriptIntro to Javascript
Intro to JavascriptAnjan Banda
 
eXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingeXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingHoat Le
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical FileSoumya Behera
 
Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]Aaron Gustafson
 
JavaScript Tutorial
JavaScript  TutorialJavaScript  Tutorial
JavaScript TutorialBui Kiet
 
Important java programs(collection+file)
Important java programs(collection+file)Important java programs(collection+file)
Important java programs(collection+file)Alok Kumar
 
Java tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry LevelJava tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry LevelRamrao Desai
 
JavaScript Objects
JavaScript ObjectsJavaScript Objects
JavaScript ObjectsReem Alattas
 
Pavel kravchenko obj c runtime
Pavel kravchenko obj c runtimePavel kravchenko obj c runtime
Pavel kravchenko obj c runtimeDneprCiklumEvents
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix TaskHermann Hueck
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upOdoo
 
Variables, expressions, standard types
 Variables, expressions, standard types  Variables, expressions, standard types
Variables, expressions, standard types Rubizza
 
Java script introducation & basics
Java script introducation & basicsJava script introducation & basics
Java script introducation & basicsH K
 

Was ist angesagt? (20)

Ad java prac sol set
Ad java prac sol setAd java prac sol set
Ad java prac sol set
 
Javascript Basics
Javascript BasicsJavascript Basics
Javascript Basics
 
Introduction to Clean Code
Introduction to Clean CodeIntroduction to Clean Code
Introduction to Clean Code
 
Intro to Javascript
Intro to JavascriptIntro to Javascript
Intro to Javascript
 
eXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingeXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction Training
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
 
Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
 
JavaScript Tutorial
JavaScript  TutorialJavaScript  Tutorial
JavaScript Tutorial
 
Java Script Best Practices
Java Script Best PracticesJava Script Best Practices
Java Script Best Practices
 
Important java programs(collection+file)
Important java programs(collection+file)Important java programs(collection+file)
Important java programs(collection+file)
 
Java tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry LevelJava tutorial for Beginners and Entry Level
Java tutorial for Beginners and Entry Level
 
JavaScript Objects
JavaScript ObjectsJavaScript Objects
JavaScript Objects
 
Pavel kravchenko obj c runtime
Pavel kravchenko obj c runtimePavel kravchenko obj c runtime
Pavel kravchenko obj c runtime
 
Future vs. Monix Task
Future vs. Monix TaskFuture vs. Monix Task
Future vs. Monix Task
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground up
 
Javascript
JavascriptJavascript
Javascript
 
Parte II Objective C
Parte II   Objective CParte II   Objective C
Parte II Objective C
 
Variables, expressions, standard types
 Variables, expressions, standard types  Variables, expressions, standard types
Variables, expressions, standard types
 
Java script introducation & basics
Java script introducation & basicsJava script introducation & basics
Java script introducation & basics
 

Ähnlich wie Objective-c Runtime

Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethodsdreampuf
 
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAPYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAMaulik Borsaniya
 
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legione-Legion
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian Feder
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitsmueller_sandsmedia
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objectsPhúc Đỗ
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportAnton Arhipov
 
Power shell examples_v4
Power shell examples_v4Power shell examples_v4
Power shell examples_v4JoeDinaso
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian Feder
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
 
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykMock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykPôle Systematic Paris-Region
 
Ast transformations
Ast transformationsAst transformations
Ast transformationsHamletDRC
 
Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Julien Truffaut
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHoward Lewis Ship
 

Ähnlich wie Objective-c Runtime (20)

Python magicmethods
Python magicmethodsPython magicmethods
Python magicmethods
 
Runtime
RuntimeRuntime
Runtime
 
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYAPYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
PYTHON-Chapter 3-Classes and Object-oriented Programming: MAULIK BORSANIYA
 
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#18.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
 
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience Report
 
Power shell examples_v4
Power shell examples_v4Power shell examples_v4
Power shell examples_v4
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
比XML更好用的Java Annotation
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
 
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej PolańczykMock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
Mock it right! A beginner’s guide to world of tests and mocks, Maciej Polańczyk
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Ocl 09
Ocl 09Ocl 09
Ocl 09
 
Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!Implicit parameters, when to use them (or not)!
Implicit parameters, when to use them (or not)!
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
 

Objective-c Runtime

  • 1. The Objective-c Runtime Павел Альбицкий p.albitsky@gmail.com
  • 4. Adding Classes objc_allocateClassPair objc_disposeClassPair objc_registerClassPair objc_duplicateClass Instantiating Classes class_createInstance objc_constructInstance objc_destructInstance Working with Instances object_copy object_dispose object_setInstanceVariable object_getInstanceVariable object_getIndexedIvars object_getIvar object_setIvar object_getClassName object_getClass object_setClass Obtaining Class Definitions objc_getClassList objc_copyClassList objc_lookUpClass objc_getClass objc_getRequiredClass objc_getMetaClass Working with Instance Variables ivar_getName ivar_getTypeEncoding ivar_getOffset Associative References objc_setAssociatedObject objc_getAssociatedObject objc_removeAssociatedObjects
  • 5. NSObject.mm + (BOOL)isKindOfClass:(Class)cls { for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; } - (BOOL)respondsToSelector:(SEL)sel { if (!sel) return NO; return class_respondsToSelector_inst([self class], sel, self); } - (BOOL)conformsToProtocol:(Protocol *)protocol { if (!protocol) return NO; for (Class tcls = [self class]; tcls; tcls = tcls->superclass) { if (class_conformsToProtocol(tcls, protocol)) return YES; } return NO; } - (id)performSelector:(SEL)sel { if (!sel) [self doesNotRecognizeSelector:sel]; return ((id(*)(id, SEL))objc_msgSend)(self, sel); }
  • 6. NSObject @interface NSObject <NSObject> { Class isa; } typedef struct objc_class *Class; struct objc_class { Class isa; #if !__OBJC2__ Class super_class const char *name long version long info long instance_size struct objc_ivar_list *ivars struct objc_method_list **methodLists struct objc_cache *cache struct objc_protocol_list *protocols #endif };
  • 7. NSObject typedef struct objc_object *id; typedef struct objc_selector *SEL; typedef struct objc_method *Method; typedef struct objc_ivar *Ivar; typedef struct objc_category *Category; typedef struct objc_property *objc_property_t; typedef struct objc_object Protocol;
  • 8. Class hierarchy @interface BaseExample : NSObject { NSString *_ivarBase; } @property(nonatomic, strong) NSString *baseProperty; - (void)test; + (NSString *)baseClassMethod; @end #import "BaseExample.h" @interface Example : BaseExample { NSString *_ivarExample; } @property(nonatomic, strong) NSString *exampleProperty; - (void)test; - (NSString *)execWithParam:(NSString *)param; + (NSString *)exampleClassMethod; @end
  • 9. Instance of Example Class Example Metaclass Example isa isa Class BaseExample isa Class NSObject isa Metaclass BaseExample Metaclass NSObject super_class super_class super_class super_class Class hierarchy
  • 10. struct objc_method { SEL method_name; // signature of method char *method_types; // types of the parameters to the method IMP method_imp; // memory address of the start of code block }; typedef struct objc_method *Method; A selector is the name used to select a method to execute for an object, or the unique identifier that replaces the name when the source code is compiled. Selector – C-string; IMP - typedef id (*IMP)(id self,SEL _cmd,...); Method
  • 11. NSString *result = [example execWithParam:@"param"]; id objc_msgSend(id self, SEL op, ...) result = objc_msgSend(example, @selector(execWithParam:), @"param"); Tail-call: typedef id (*IMP)(id self,SEL _cmd,...); void objc_msgSend(void /* id self, SEL op, ... */ ) NSString *result = ((NSString* (*)(id, SEL, NSString *))objc_msgSend)(example, @selector(execWithParam:), @"param"); Sending Messages
  • 12. id objc_msgSend(id self, SEL op, ...) Sends a message with a simple return value to an instance of a class. double objc_msgSend_fpret(id self, SEL op, ...) Sends a message with a floating-point return value to an instance of a class. void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...) Sends a message with a data-structure return value to an instance of a class. id objc_msgSendSuper(struct objc_super *super, SEL op, ...) Sends a message with a simple return value to the superclass of an instance of a class. void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...) Sends a message with a data-structure return value to the superclass of an instance of a class. objc_msgSend
  • 14. resolveInstanceMethod 1. Class cache -> class dispatch table -> all super classes 2. resolveInstanceMethod for @dynamic properties id dynamicGetter(id self, SEL _cmd); void dynamicSetter(id self, SEL _cmd, id value); + (BOOL)isDynamicProperty:(NSString *)selectorString; + (BOOL)resolveInstanceMethod:(SEL)sel { NSString *selectorString = NSStringFromSelector(sel); if ([self isDynamicProperty:selectorString]) { if ([selectorString hasPrefix:@"set"]) { class_addMethod(self, sel, (IMP)dynamicSetter, "v@:@"); } else { class_addMethod(sel, sel, (IMP)dynamicGetter, "@@:"); } return YES; } return [super resolveInstanceMethod:sel]; } // "v@:@", "@@:" - Objective-C type encodings
  • 15. forwardingTargetForSelector 3. The Runtime then calls forwardingTargetForSelector Returns the object to which unrecognized messages should first be directed. - (id)forwardingTargetForSelector:(SEL)aSelector { if (aSelector == @selector(magicMethod:)) { return magicObject; } else { return [super forwardingTargetForSelector:aSelector]; } }
  • 16. forwardInvocation @implementation InvClass - (NSString *)invWithFirst:(NSString *)first second:(NSNumber *)second third:(NSArray *)third { return [NSString stringWithFormat:@"first: %@, second: %@, third: %@", first, second, third]; } @end // perform unrecognized selector Example *example = [Example new]; SEL selector = @selector(invWithFirst:); NSString *result = [example performSelector:selector withObject:@"first"];
  • 17. forwardInvocation + (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(invWithFirst:)) { return NO; } return YES; } - (id)forwardingTargetForSelector:(SEL)aSelector { if (aSelector == @selector(invWithFirst:)) { return nil; } return [super forwardingTargetForSelector:aSelector]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature* signature = [super methodSignatureForSelector:aSelector]; if (!signature) { SEL customSelector = @selector(invWithFirst:second:third:); signature = [_invObject methodSignatureForSelector:customSelector]; } return signature; }
  • 18. forwardInvocation - (void)forwardInvocation:(NSInvocation *)anInvocation { SEL selector = anInvocation.selector; if ([_invObject respondsToSelector:selector]) { [anInvocation setTarget:_invObject]; SEL customSelector = @selector(invWithFirst:second:third:); [anInvocation setSelector:customSelector]; NSString *first = @"first"; NSNumber *second = @2; NSArray *third = @[@”3", @”33”, @”333"]; [anInvocation setArgument:&first atIndex:2]; [anInvocation setArgument:&second atIndex:3]; [anInvocation setArgument:&third atIndex:4]; [anInvocation invoke]; } else { [self doesNotRecognizeSelector:selector]; } }
  • 20. #import <objc/runtime.h> @import Crashlytics; @implementation UIViewController (Tracking) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class class = [self class]; SEL originalSelector = @selector(viewWillAppear:); SEL swizzledSelector = @selector(swizzled_viewWillAppear:); Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (didAddMethod) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }); } - (void)swizzled_viewWillAppear:(BOOL)animated { CLS_LOG(@"CLSLOG viewWillAppear: %@", self); [self swizzled_viewWillAppear:animated]; } @end
  • 21. URLs • Mike Ash • Objective-C Runtime Reference • Objective-C Runtime Programming Guide • opensource.apple.com
  • 22. Спасибо за внимание! Павел Альбицкий p.albitsky@gmail.com