SlideShare a Scribd company logo
Objective-C Runtime
Examples	

https://github.com/storoj/objc_runtime_examples
Example 1.1
Observe value changes for all properties of a given class.
Class
Property
(objc_property_t)

getter
setter

Method
SEL

IMP
Sample class
@interface ELSample : NSObject
!
@property (nonatomic, strong) NSArray *values;
@property (nonatomic,
assign,
getter=isValid,
setter=setValidCustom:) BOOL valid;
!
@end
!
@implementation ELSample
!
@synthesize valid = ivar_valid;
!
@end

Recommended for you

Node js mongodriver
Node js mongodriverNode js mongodriver
Node js mongodriver

Hamburg presentation of the Node.js driver building a simple location based app using express.js and mongodb.

What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6

The document provides an overview of new features introduced in C# 6.0, including static using, string interpolation, dictionary initializers, auto-property initializers, nameof expression, await in catch/finally blocks, null conditional operator, expression-bodied members, and extension methods used with static using. Code examples are provided to demonstrate the usage of each new feature.

c# 6newexamples
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine

This document discusses using Jasmine to test JavaScript code. It describes Jasmine as a behavior driven development framework for JavaScript testing. It then provides instructions on installing Jasmine, creating spec files to contain test cases, and including source code files. The document uses an example of testing a master-slave checkbox relationship to demonstrate how to set up tests, DOM elements, and code the tests against the actual code implementation.

bddjavascriptjasmine
Class
Class sampleClass1 = [ELSample class];
Class sampleClass2 = NSClassFromString(@"ELSample");
#import <objc/runtime.h>
!
Class sampleClass3 = objc_getClass(“ELSample");
Class sampleClass4 = objc_lookUpClass(“ELSample");
Properties
unsigned int propertyCount = 0;
objc_property_t *properties = class_copyPropertyList(
sampleClass,
&propertyCount
);
!
for (unsigned int i=0; i<propertyCount; i++) {
objc_property_t property = properties[i];
!
const char *propertyName = property_getName(property);
NSLog(@"%s", propertyName);
}
free(properties);
Output:
values
valid
Property attributes
char const *attributesString = property_getAttributes(property);
NSLog(@"%s %s", propertyName, attributesString);
Output:
values T@"NSArray",&,N,V_values
valid Tc,N,GisValid,SsetValidCustom:,Vivar_valid

Code

Meaning

T

type (c - char, @ - id)

N

nonatomic

G

getter selector

S

setter selector

V

ivar name

&

strong/retain
More info
Property setter
/**
* @return The value string of the attribute attributeName if it exists in
* property, nil otherwise.
*/

!
char *property_copyAttributeValue(objc_property_t property,
const char *attributeName)

char *setterAttributeValue = property_copyAttributeValue(property, "S");
if (NULL == setterAttributeValue) {
"set" + capitalize(property_getName(property)) + ":"
}
// do not forget!
free(setterAttributeValue);

Recommended for you

Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheel

The document discusses the Apache Commons project, which develops reusable Java components. It notes that Commons components allow for faster and smaller development by avoiding reinventing common functions. The document outlines several active Commons components like Collections, IO, Lang, and Logging, as well as sandbox and dormant components. It emphasizes that 80% of Commons components have no dependencies on each other, promoting flexibility and reuse.

2008apacheconapache
The zen of async: Best practices for best performance
The zen of async: Best practices for best performanceThe zen of async: Best practices for best performance
The zen of async: Best practices for best performance

The document discusses async/await in .NET and C#. It is aimed at .NET library developers to help them understand when and how to properly implement async methods. The key topics covered are getting the right mental model for async/await, knowing when not to use async, avoiding allocations, and minimizing suspensions. Examples are provided of manually caching tasks to improve performance compared to unnecessary allocations.

c#developeralex turner
Spock and Geb
Spock and GebSpock and Geb
Spock and Geb

The document provides an overview of the Spock testing framework for Java Virtual Machine (JVM) applications. It describes Spock as a behavior-driven development (BDD) testing tool that can be used for both unit and system tests. Spock tests use a given-when-then structure and various blocks like setup, cleanup, and where to define fixtures, exercise code, and make assertions. It also supports features like parameterized tests, helper methods, and powerful assertions.

Method invocation
id objc_msgSend(id self, SEL _cmd, ...)
ELSample *sample = [ELSample new];
sample.valid = YES;
[sample setValidCustom:YES];
objc_msgSend(sample, @selector(setValidCustom:), YES);
id objc_msgSend(id self, SEL _cmd, ...)
{
IMP methodFunction = [[self class] methodForSelector:_cmd];
return methodFunction(self, _cmd, ...);
}
Method
Method *class_copyMethodList(Class cls, unsigned int *outCount)
!
Method class_getInstanceMethod(Class cls, SEL name)
!
Method class_getClassMethod(Class cls, SEL name)
IMP method_getImplementation(Method m)
!
/**
* @return The previous implementation of the method.
*/
IMP method_setImplementation(Method m, IMP imp)
Replacing method implementation
IMP method_setImplementation(Method m, IMP imp)
@interface Sample : NSObject
- (id)swizzleMe:(NSInteger)arg;
@end
Method method = class_getInstanceMethod(class, @selector(swizzleMe:));
typedef id (*IMP)(id, SEL, ...);
id SwizzleFunction(id self, SEL _cmd, NSInteger arg)
{
return @(arg+5);
}

!

method_setImplementation(method, (IMP)SwizzleFunction);
Blocks
id(^block)(id, id) = ^id(id self, id arg) {
NSLog(@"arg: %@", arg);
return nil;
};
IMP blockImp = imp_implementationWithBlock(block);

Block can capture original IMP to call it later.

Recommended for you

I os 04
I os 04I os 04
I os 04

This document discusses UIPickerView and NSArray in iOS app development. It includes sections on NSArray classes like NSArray and NSMutableArray, how to initialize and access array objects. It also covers the UIPickerView, UIPickerViewDataSource, and UIPickerViewDelegate protocols. Example projects are described that show how to generate a UIPickerView programmatically or using a XIB file and populate it with array data. Projects also demonstrate handling selection of multiple components and dependent picker views.

ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016

The document provides an agenda for a talk on modeling a Rubik's Cube in JavaScript. It begins with an introduction to scripting languages and ECMAScript. It then discusses modeling a Rubik's Cube by first walking through the code, then modeling the cube and finding moves to solve it. The document covers topics like scripting languages, ECMAScript, object-oriented programming concepts in JavaScript, and modeling a Rubik's Cube to be manipulated programmatically.

V8
V8V8
V8

V8 is the JavaScript engine used in Google Chrome. It is open source and written in C++ with some parts implemented in embedded JavaScript. V8 uses just-in-time compilation, precise garbage collection, inline caching, and hidden classes to optimize performance. It supports 64-bit versions and has advantages like C-like syntax and bit operations. While documentation is limited, it allows embedding JavaScript in C++ applications and extending it with user libraries.

kasastudy
NSString *setterName = property_getSetterName(property);
SEL setterSelector = NSSelectorFromString(setterName);
!
Method method = class_getInstanceMethod(class, setterSelector);
IMP originalImp = method_getImplementation(method);
!
id(^block)(id, ...) = ^id(id self, ...) {
NSLog(@"will change %s", property_getName(property));
return originalImp(self, setterSelector, ...);
};
!
IMP newImp = imp_implementationWithBlock(block);
!
method_setImplementation(method, newImp);

BUT…
return originalImp(self, setterSelector, ...);
(self, setterSelector, ...);
...

F*CK
Cast to concrete type
void(^block)(id, id) = ^void(id self, id arg) {
((void(*)(id, SEL, id))originalImp)(self, selector, arg);
};
// 0 - self, 1 - _cmd
char *argumentEncoding = method_copyArgumentType(method, 2);

id block = nil;
if (0 == strcmp(argumentEncoding, @encode(NSInteger))) {
block = ^void(id self, SEL selector, NSInteger arg) {
((void(*)(id, SEL, NSInteger))originalImp)(self, sel, arg);
};
} else if (...) {
...
}
Example 1.2
_objc_msgForward
id _objc_msgForward(id receiver, SEL sel, ...)
!
will call forwardInvocation: with prepared NSInvocation object

Method method = class_getInstanceMethod(class, setterSelector);
!
IMP originalImp = method_setImplementation(method, _objc_msgForward);
NSString *internalSetterName = [setterName
stringByAppendingString:@"_internal"];
SEL internalSelector = NSSelectorFromString(internalSetterName);
char const *types = method_getTypeEncoding(method);
class_addMethod(class, internalSelector, originalImp, types);
[capturedSelectorsSet addObject:setterName];

Recommended for you

Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss

This document discusses several popular Java libraries including: - Dependency injection frameworks like Guice and Spring - Logging with SLF4J - Collections and utilities with Guava - HTTP clients like OkHttp - Reactive programming with RxJava - REST with Retrofit - Asynchronous programming with JDeferred - Event handling with MBassador - Code generation with Lombok and ByteBuddy - Testing utilities like JUnitParams, Mockito, Jukito, and Spock - Waiting assertions with Awaitility and REST testing with Rest-assured.

devoxxjava
Scala in practice
Scala in practiceScala in practice
Scala in practice

This document provides an overview of Scala and compares it to Java. It discusses Scala's object-oriented and functional capabilities, how it compiles to JVM bytecode, and benefits like less boilerplate code and support for functional programming. Examples are given of implementing a simple Property class in both Java and Scala to illustrate concepts like case classes, immutable fields, and less lines of code in Scala. The document also touches on Java interoperability, learning Scala gradually, XML processing capabilities, testing frameworks, and tool/library support.

scala
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks

MongoDB is the trusted document store we turn to when we have tough data store problems to solve. For this talk we are going to go a little bit off the path and explore what other roles we can fit MongoDB into. Others have discussed how to turn MongoDB’s capped collections into a publish/subscribe server. We stretch that a little further and turn MongoDB into a full fledged broker with both publish/subscribe and queue semantics, and a the ability to mix them. We will provide code and a running demo of the queue producers and consumers. Next we will turn to coordination services: We will explore the fundamental features and show how to implement them using MongoDB as the storage engine. Again we will show the code and demo the coordination of multiple applications.

Replace forwardInvocation:
Method method = class_getInstanceMethod(class, @selector(forwardInvocation:));
IMP originalImp = method_getImplementation(method);

!

void(^block)(id, NSInvocation *) = ^void(id self, NSInvocation *invocation) {
NSString *selectorName = NSStringFromSelector([invocation selector]);

!

!

if ([capturedSelectorsSet containsObject:selectorName]) {
NSString *internalSelectorName = [selectorName
stringByAppendingString:@“_internal"];
[invocation setSelector:NSSelectorFromString(internalSelectorName)];
[invocation invoke];
} else {
((void(*)(id, SEL, NSInvocation *)) originalImp)(self,
@selector(forwardInvocation:),
invocation);
}

};

!

method_setImplementation(method, imp_implementationWithBlock(block));
Example 1.3
Replace the class
Class object_setClass(id obj, Class cls)
NSNumber *number = [NSNumber numberWithDouble:5.1f];
!
Class class = [number class];
NSLog(@"number: %@ %@ %p", number, class, (__bridge void *)number);
// number: 5.099999904632568 __NSCFNumber 0x8d464c0
!
object_setClass(number, [NSObject class]);
NSLog(@"number: %@", number);
// number: <NSObject: 0x8d464c0>
object_setClass(number, class);
NSLog(@"number: %@", number);
// number: 5.099999904632568
NSProxy
“… Subclasses of NSProxy can be used to
implement transparent distributed messaging…”

Some people, when confronted with a
problem, think "I know, I'll use NSProxy." Now
they have two problems.

Recommended for you

Implementing CQRS and Event Sourcing with RavenDB
Implementing CQRS and Event Sourcing with RavenDBImplementing CQRS and Event Sourcing with RavenDB
Implementing CQRS and Event Sourcing with RavenDB

CQRS stands for Command Query Responsibility Segregation. That is, that command stack and query stack are designed separately. This leads to a dramatic simplification of design and potential enhancement of scalability. Events are a new trend in software industry. In real-world, we perform actions and these actions generate a reaction. Event Sourcing is about persisting events and rebuilding the state of the aggregates from recorded events. In this talk I will share a lot of examples about how to effective implementing CQRS and Event Sourcing with RavenDB

architecturebig datanosql
From C++ to Objective-C
From C++ to Objective-CFrom C++ to Objective-C
From C++ to Objective-C

This document provides an overview of moving from C++ to Objective-C. It discusses key differences in syntax between the two languages, including differences in class and method declarations. It also covers Objective-C specific topics like protocols, properties, memory management using retain/release, and the role of the NSAutoreleasePool in autoreleasing objects. The document is intended to act as a bridge for developers familiar with C++ to understand fundamental concepts for working with Objective-C.

c++c++ corehard spring 2018obj-c
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript

The document discusses working with code abstract syntax trees (ASTs). It provides examples of parsing code into ASTs using libraries like Esprima, querying ASTs using libraries like grasp-equery, constructing and transforming ASTs, and generating code from ASTs. It introduces aster, an AST-based code builder that allows defining reusable AST transformations as plugins and integrating AST-based builds into generic build systems like Grunt and Gulp. Aster aims to improve on file-based builders by working directly with ASTs in a streaming fashion.

source codejavascriptmetaprogramming
@interface Observer : NSProxy
+ (instancetype)observerWithObject:(id)object;
@end

!

@implementation Observer

!

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
Class realClass = objc_getAssociatedObject(self, "realClass");
SEL selector = [anInvocation selector];
objc_property_t property = class_getPropertyWithSetter(realClass, selector);
if (NULL != property) {
NSLog(@"changing %s", property_getName(property));
}

!

}

Class currentClass = [self class];
object_setClass(self, realClass);
[anInvocation invoke];
object_setClass(self, currentClass);

!

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
Class realClass = objc_getAssociatedObject(self, "realClass");
NSMethodSignature *sig = [realClass instanceMethodSignatureForSelector:sel];
return signature;
}

!

@end
Example 2
Get outlets and actions runtime
UIRuntimeConnection
UIRuntimeOutletConnection

UIRuntimeEventConnection

UIRuntimeOutletCollectionConnection
@interface UIRuntimeConnection : NSObject <NSCoding>
!
@property (nonatomic, strong) id destination;
@property (nonatomic, strong) NSString *label;
@property (nonatomic, strong) id source;
!
- (void)connect;
- (void)connectForSimulator;
!
@end
!
@interface UIRuntimeEventConnection : UIRuntimeConnection
!
@property (nonatomic, readonly) SEL action;
@property (nonatomic, assign) UIControlEvents eventMask;
@property (nonatomic, readonly) id target;
!
@end
!
@interface UIRuntimeOutletConnection : UIRuntimeConnection
@end

Recommended for you

Phactory
PhactoryPhactory
Phactory

Phactory is an alternative to database fixtures for defining test data in PHP unit tests. It allows developers to define database objects in code and dynamically create them, rather than loading static datasets. Phactory provides a lightweight ORM and works with MySQL, SQLite, and MongoDB. It supports defining object blueprints, creating objects with associations, retrieving objects, and integrating with PHPUnit for testing database code.

fixturephptesting
JavaScript Design Patterns
JavaScript Design PatternsJavaScript Design Patterns
JavaScript Design Patterns

Great design patterns are reusable, modular expressions of what’s going on in your code. They allow you to communicate to other developers simply by the way you code, in addition to being easily maintainable themselves. Put simply, patterns are the available tools in the developer’s toolbox. In this presentation, I review a few common patterns, their advantages/disadvantages, and how they can be implemented. The source for this presentation can be found here: https://github.com/derekbrown/designpatterns

javascriptobject-oriented programmingweb development
Objective-c Runtime
Objective-c RuntimeObjective-c Runtime
Objective-c Runtime

The document discusses the Objective-C runtime and provides an overview of its main components and functions. It describes how the runtime works with classes, instances, methods, and message passing. It also covers topics like method resolution, forwarding, and method swizzling. Code examples are provided to illustrate concepts like forwarding messages and swizzling methods. URLs are included for additional Objective-C runtime references and documentation.

iosobjective-cruntume
kennytm
https://github.com/kennytm/iphone-private-frameworks

class-dump-z
https://code.google.com/p/networkpx/wiki/class_dump_z

runtime
Class *objc_copyClassList(unsigned int *outCount)
Protocol * __unsafe_unretained *objc_copyProtocolList(unsigned int *outCount)
Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
Method *class_copyMethodList(Class cls, unsigned int *outCount)
Protocol * __unsafe_unretained *class_copyProtocolList(Class cls,
unsigned int *outCount)
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
SEL selector = NSSelectorFromString(@"initWithCoder:");

!

Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection");
Method outletMethod = class_getInstanceMethod(outletClass, selector);
method_swizzle(outletMethod, ...);

!

Class eventClass = NSClassFromString(@"UIRuntimeEventConnection");
Method eventMethod = class_getInstanceMethod(eventClass, selector);
method_swizzle(eventMethod, ...)

NO!
Why not?.. Looks good.
SEL selector = NSSelectorFromString(@"initWithCoder:");

!

Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection");
Method outletMethod = class_getInstanceMethod(outletClass, selector);

!

Class eventClass = NSClassFromString(@"UIRuntimeEventConnection");
Method eventMethod = class_getInstanceMethod(eventClass, selector);

!

Class baseClass = NSClassFromString(@"UIRuntimeConnection");
Method baseMethod = class_getInstanceMethod(baseClass, selector);

!

baseMethod == outletMethod
baseMethod != eventMethod
@implementation UIRuntimeEventConnection

!

- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// decode eventMask
}
return self;
}

!

@end
Copy method before swizzling
SEL selector = NSSelectorFromString(@"initWithCoder:");

!

Class baseClass = NSClassFromString(@"UIRuntimeConnection");
Method baseMethod = class_getInstanceMethod(baseClass, selector);

!

Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection");
class_addMethod(outletClass, selector,
method_getImplementation(baseMethod),
method_getTypeEncoding(baseMethod));

!

Method outletMethod = class_getInstanceMethod(outletClass, selector);

!

method_swizzle(outletMethod, ...);

Recommended for you

Runtime
RuntimeRuntime
Runtime

Objective-C is an object-oriented programming language that uses message passing to communicate between objects. Objects are represented as C structs with a pointer to their class. The class struct contains metadata about the class like its name, methods, and properties. Objective-C uses a dynamic runtime that allows objects to be modified at runtime via mechanisms like method swizzling and isa swizzling.

iosmac os x
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development

The document discusses iPhone app development using Objective-C. It covers the basics of getting started, including what is needed to begin like a Mac, Xcode, and an iPhone. It then explains key Objective-C concepts like classes, methods, and memory management using retain counts. The document also discusses unit testing iOS apps using OCUnit and some Xcode tips. It emphasizes testing first and concludes by noting the market demands more apps and there is room for improvement.

objectivecbddcoding dojo
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」

The document shows examples of using blocks and closures in Objective-C and C++, including passing blocks as parameters to functions and defining block types. It also demonstrates capturing values from outer scopes within blocks by copying blocks. Various block examples are provided to illustrate block syntax and usage.

Be a man!
SEL selector = NSSelectorFromString(@"initWithCoder:");

!

Class baseClass = NSClassFromString(@"UIRuntimeConnection");
Method baseMethod = class_getInstanceMethod(baseClass, selector);

!

Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection");

!

id(^initWithCoderBlock)(id, id) = ^id(id aSelf, id aDecoder) {
struct objc_super _super = {
.receiver = aSelf,
.super_class = [[aSelf class] superclass]
};

!

return objc_msgSendSuper(&_super, selector, aDecoder);

};
IMP initWithCoderImp = imp_implementationWithBlock(initWithCoderBlock);

!

class_addMethod(outletClass, selector, initWithCoderImp,
method_getTypeEncoding(baseMethod));
Output
UIStoryboardScene got ELViewController *sceneViewController
ELViewController got UIStoryboard *storyboard
UIControlEventTouchUpInside -[ELViewController buttonTap:(UIButton *)]
UIControlEventEditingChanged -[ELViewController
datePickerEditingChanged:(UIDatePicker *)]
UITableView got ELViewController *dataSource
ELViewController got UIDatePicker *datePicker
UITableView got ELViewController *delegate
ELViewController got UILabel *label
ELViewController got UIView *view
Useful links
•
•
•
•
•
•
•

Property introspection	

imp_implementationWithBlock	

class loading and initialization	

let's build objc_msgSend	

objc_msgSend ARM assembly	

private frameworks	

Objective-C Runtime Programming Guide

More Related Content

What's hot

Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
go_oh
 
Js 单元测试框架介绍
Js 单元测试框架介绍Js 单元测试框架介绍
Js 单元测试框架介绍
louieuser
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns Reconsidered
Alex Miller
 
Node js mongodriver
Node js mongodriverNode js mongodriver
Node js mongodriver
christkv
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6
Fiyaz Hasan
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheel
tcurdt
 
The zen of async: Best practices for best performance
The zen of async: Best practices for best performanceThe zen of async: Best practices for best performance
The zen of async: Best practices for best performance
Microsoft Developer Network (MSDN) - Belgium and Luxembourg
 
Spock and Geb
Spock and GebSpock and Geb
Spock and Geb
Christian Baranowski
 
I os 04
I os 04I os 04
I os 04
信嘉 陳
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
Manoj Kumar
 
V8
V8V8
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss
Andres Almiray
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
andyrobinson8
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
MongoDB
 
Implementing CQRS and Event Sourcing with RavenDB
Implementing CQRS and Event Sourcing with RavenDBImplementing CQRS and Event Sourcing with RavenDB
Implementing CQRS and Event Sourcing with RavenDB
Oren Eini
 
From C++ to Objective-C
From C++ to Objective-CFrom C++ to Objective-C
From C++ to Objective-C
corehard_by
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript
Ingvar Stepanyan
 
Phactory
PhactoryPhactory
Phactory
chriskite
 
JavaScript Design Patterns
JavaScript Design PatternsJavaScript Design Patterns
JavaScript Design Patterns
Derek Brown
 

What's hot (20)

Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Js 单元测试框架介绍
Js 单元测试框架介绍Js 单元测试框架介绍
Js 单元测试框架介绍
 
Design Patterns Reconsidered
Design Patterns ReconsideredDesign Patterns Reconsidered
Design Patterns Reconsidered
 
Node js mongodriver
Node js mongodriverNode js mongodriver
Node js mongodriver
 
What’s new in C# 6
What’s new in C# 6What’s new in C# 6
What’s new in C# 6
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheel
 
The zen of async: Best practices for best performance
The zen of async: Best practices for best performanceThe zen of async: Best practices for best performance
The zen of async: Best practices for best performance
 
Spock and Geb
Spock and GebSpock and Geb
Spock and Geb
 
I os 04
I os 04I os 04
I os 04
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
V8
V8V8
V8
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Implementing CQRS and Event Sourcing with RavenDB
Implementing CQRS and Event Sourcing with RavenDBImplementing CQRS and Event Sourcing with RavenDB
Implementing CQRS and Event Sourcing with RavenDB
 
From C++ to Objective-C
From C++ to Objective-CFrom C++ to Objective-C
From C++ to Objective-C
 
AST - the only true tool for building JavaScript
AST - the only true tool for building JavaScriptAST - the only true tool for building JavaScript
AST - the only true tool for building JavaScript
 
Phactory
PhactoryPhactory
Phactory
 
JavaScript Design Patterns
JavaScript Design PatternsJavaScript Design Patterns
JavaScript Design Patterns
 

Similar to «Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion

Objective-c Runtime
Objective-c RuntimeObjective-c Runtime
Objective-c Runtime
Pavel Albitsky
 
Runtime
RuntimeRuntime
Runtime
Jorge Ortiz
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
Giordano Scalzo
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
matuura_core
 
Prototype Framework
Prototype FrameworkPrototype Framework
Prototype Framework
Julie Iskander
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
HamletDRC
 
Java Script Workshop
Java Script WorkshopJava Script Workshop
Java Script Workshop
Dmitry Baranovskiy
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
HamletDRC
 
Functional Core, Reactive Shell
Functional Core, Reactive ShellFunctional Core, Reactive Shell
Functional Core, Reactive Shell
Giovanni Lodi
 
Pavel kravchenko obj c runtime
Pavel kravchenko obj c runtimePavel kravchenko obj c runtime
Pavel kravchenko obj c runtime
DneprCiklumEvents
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
HamletDRC
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
Piyush Katariya
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
Hussain Behestee
 
Swift와 Objective-C를 함께 쓰는 방법
Swift와 Objective-C를 함께 쓰는 방법Swift와 Objective-C를 함께 쓰는 방법
Swift와 Objective-C를 함께 쓰는 방법
Jung Kim
 
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
Maulik Borsaniya
 
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docxsrcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
whitneyleman54422
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
Phúc Đỗ
 
Metaprogramming in JavaScript
Metaprogramming in JavaScriptMetaprogramming in JavaScript
Metaprogramming in JavaScript
Mehdi Valikhani
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
Julie Iskander
 
Javascript
JavascriptJavascript
Javascript
Aditya Gaur
 

Similar to «Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion (20)

Objective-c Runtime
Objective-c RuntimeObjective-c Runtime
Objective-c Runtime
 
Runtime
RuntimeRuntime
Runtime
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
 
Prototype Framework
Prototype FrameworkPrototype Framework
Prototype Framework
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
Java Script Workshop
Java Script WorkshopJava Script Workshop
Java Script Workshop
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 
Functional Core, Reactive Shell
Functional Core, Reactive ShellFunctional Core, Reactive Shell
Functional Core, Reactive Shell
 
Pavel kravchenko obj c runtime
Pavel kravchenko obj c runtimePavel kravchenko obj c runtime
Pavel kravchenko obj c runtime
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
 
Swift와 Objective-C를 함께 쓰는 방법
Swift와 Objective-C를 함께 쓰는 방법Swift와 Objective-C를 함께 쓰는 방법
Swift와 Objective-C를 함께 쓰는 방법
 
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
 
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docxsrcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
srcArtifact.javasrcArtifact.javaclassArtifactextendsCave{pub.docx
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
Metaprogramming in JavaScript
Metaprogramming in JavaScriptMetaprogramming in JavaScript
Metaprogramming in JavaScript
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
Javascript
JavascriptJavascript
Javascript
 

More from e-Legion

MBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, PureMBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, Pure
e-Legion
 
MBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetricaMBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetrica
e-Legion
 
MBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba MobileMBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba Mobile
e-Legion
 
MBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha RestoranyMBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha Restorany
e-Legion
 
MBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500StartupsMBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500Startups
e-Legion
 
MBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, AviasalesMBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, Aviasales
e-Legion
 
MBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank OnlineMBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank Online
e-Legion
 
Rx Java architecture
Rx Java architectureRx Java architecture
Rx Java architecture
e-Legion
 
Rx java
Rx javaRx java
Rx java
e-Legion
 
MBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, SpotifyMBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, Spotify
e-Legion
 
MBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, WunderlistMBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, Wunderlist
e-Legion
 
MBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, SoundcloudMBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, Soundcloud
e-Legion
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Co
e-Legion
 
MBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, PostforpostMBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, Postforpost
e-Legion
 
MBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, ParallelsMBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, Parallels
e-Legion
 
MBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DITMBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DIT
e-Legion
 
MBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, LitresMBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, Litres
e-Legion
 
MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box
e-Legion
 
MBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, MicrosoftMBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, Microsoft
e-Legion
 
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
e-Legion
 

More from e-Legion (20)

MBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, PureMBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, Pure
 
MBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetricaMBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetrica
 
MBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba MobileMBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba Mobile
 
MBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha RestoranyMBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha Restorany
 
MBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500StartupsMBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500Startups
 
MBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, AviasalesMBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, Aviasales
 
MBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank OnlineMBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank Online
 
Rx Java architecture
Rx Java architectureRx Java architecture
Rx Java architecture
 
Rx java
Rx javaRx java
Rx java
 
MBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, SpotifyMBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, Spotify
 
MBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, WunderlistMBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, Wunderlist
 
MBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, SoundcloudMBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, Soundcloud
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Co
 
MBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, PostforpostMBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, Postforpost
 
MBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, ParallelsMBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, Parallels
 
MBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DITMBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DIT
 
MBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, LitresMBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, Litres
 
MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box
 
MBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, MicrosoftMBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, Microsoft
 
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
 

«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion

  • 2. Example 1.1 Observe value changes for all properties of a given class.
  • 4. Sample class @interface ELSample : NSObject ! @property (nonatomic, strong) NSArray *values; @property (nonatomic, assign, getter=isValid, setter=setValidCustom:) BOOL valid; ! @end ! @implementation ELSample ! @synthesize valid = ivar_valid; ! @end
  • 5. Class Class sampleClass1 = [ELSample class]; Class sampleClass2 = NSClassFromString(@"ELSample"); #import <objc/runtime.h> ! Class sampleClass3 = objc_getClass(“ELSample"); Class sampleClass4 = objc_lookUpClass(“ELSample");
  • 6. Properties unsigned int propertyCount = 0; objc_property_t *properties = class_copyPropertyList( sampleClass, &propertyCount ); ! for (unsigned int i=0; i<propertyCount; i++) { objc_property_t property = properties[i]; ! const char *propertyName = property_getName(property); NSLog(@"%s", propertyName); } free(properties); Output: values valid
  • 7. Property attributes char const *attributesString = property_getAttributes(property); NSLog(@"%s %s", propertyName, attributesString); Output: values T@"NSArray",&,N,V_values valid Tc,N,GisValid,SsetValidCustom:,Vivar_valid Code Meaning T type (c - char, @ - id) N nonatomic G getter selector S setter selector V ivar name & strong/retain More info
  • 8. Property setter /** * @return The value string of the attribute attributeName if it exists in * property, nil otherwise. */ ! char *property_copyAttributeValue(objc_property_t property, const char *attributeName) char *setterAttributeValue = property_copyAttributeValue(property, "S"); if (NULL == setterAttributeValue) { "set" + capitalize(property_getName(property)) + ":" } // do not forget! free(setterAttributeValue);
  • 9. Method invocation id objc_msgSend(id self, SEL _cmd, ...) ELSample *sample = [ELSample new]; sample.valid = YES; [sample setValidCustom:YES]; objc_msgSend(sample, @selector(setValidCustom:), YES); id objc_msgSend(id self, SEL _cmd, ...) { IMP methodFunction = [[self class] methodForSelector:_cmd]; return methodFunction(self, _cmd, ...); }
  • 10. Method Method *class_copyMethodList(Class cls, unsigned int *outCount) ! Method class_getInstanceMethod(Class cls, SEL name) ! Method class_getClassMethod(Class cls, SEL name) IMP method_getImplementation(Method m) ! /** * @return The previous implementation of the method. */ IMP method_setImplementation(Method m, IMP imp)
  • 11. Replacing method implementation IMP method_setImplementation(Method m, IMP imp) @interface Sample : NSObject - (id)swizzleMe:(NSInteger)arg; @end Method method = class_getInstanceMethod(class, @selector(swizzleMe:)); typedef id (*IMP)(id, SEL, ...); id SwizzleFunction(id self, SEL _cmd, NSInteger arg) { return @(arg+5); } ! method_setImplementation(method, (IMP)SwizzleFunction);
  • 12. Blocks id(^block)(id, id) = ^id(id self, id arg) { NSLog(@"arg: %@", arg); return nil; }; IMP blockImp = imp_implementationWithBlock(block); Block can capture original IMP to call it later.
  • 13. NSString *setterName = property_getSetterName(property); SEL setterSelector = NSSelectorFromString(setterName); ! Method method = class_getInstanceMethod(class, setterSelector); IMP originalImp = method_getImplementation(method); ! id(^block)(id, ...) = ^id(id self, ...) { NSLog(@"will change %s", property_getName(property)); return originalImp(self, setterSelector, ...); }; ! IMP newImp = imp_implementationWithBlock(block); ! method_setImplementation(method, newImp); BUT… return originalImp(self, setterSelector, ...); (self, setterSelector, ...); ... F*CK
  • 14. Cast to concrete type void(^block)(id, id) = ^void(id self, id arg) { ((void(*)(id, SEL, id))originalImp)(self, selector, arg); }; // 0 - self, 1 - _cmd char *argumentEncoding = method_copyArgumentType(method, 2); id block = nil; if (0 == strcmp(argumentEncoding, @encode(NSInteger))) { block = ^void(id self, SEL selector, NSInteger arg) { ((void(*)(id, SEL, NSInteger))originalImp)(self, sel, arg); }; } else if (...) { ... }
  • 16. _objc_msgForward id _objc_msgForward(id receiver, SEL sel, ...) ! will call forwardInvocation: with prepared NSInvocation object Method method = class_getInstanceMethod(class, setterSelector); ! IMP originalImp = method_setImplementation(method, _objc_msgForward); NSString *internalSetterName = [setterName stringByAppendingString:@"_internal"]; SEL internalSelector = NSSelectorFromString(internalSetterName); char const *types = method_getTypeEncoding(method); class_addMethod(class, internalSelector, originalImp, types); [capturedSelectorsSet addObject:setterName];
  • 17. Replace forwardInvocation: Method method = class_getInstanceMethod(class, @selector(forwardInvocation:)); IMP originalImp = method_getImplementation(method); ! void(^block)(id, NSInvocation *) = ^void(id self, NSInvocation *invocation) { NSString *selectorName = NSStringFromSelector([invocation selector]); ! ! if ([capturedSelectorsSet containsObject:selectorName]) { NSString *internalSelectorName = [selectorName stringByAppendingString:@“_internal"]; [invocation setSelector:NSSelectorFromString(internalSelectorName)]; [invocation invoke]; } else { ((void(*)(id, SEL, NSInvocation *)) originalImp)(self, @selector(forwardInvocation:), invocation); } }; ! method_setImplementation(method, imp_implementationWithBlock(block));
  • 19. Replace the class Class object_setClass(id obj, Class cls) NSNumber *number = [NSNumber numberWithDouble:5.1f]; ! Class class = [number class]; NSLog(@"number: %@ %@ %p", number, class, (__bridge void *)number); // number: 5.099999904632568 __NSCFNumber 0x8d464c0 ! object_setClass(number, [NSObject class]); NSLog(@"number: %@", number); // number: <NSObject: 0x8d464c0> object_setClass(number, class); NSLog(@"number: %@", number); // number: 5.099999904632568
  • 20. NSProxy “… Subclasses of NSProxy can be used to implement transparent distributed messaging…” Some people, when confronted with a problem, think "I know, I'll use NSProxy." Now they have two problems.
  • 21. @interface Observer : NSProxy + (instancetype)observerWithObject:(id)object; @end ! @implementation Observer ! - (void)forwardInvocation:(NSInvocation *)anInvocation { Class realClass = objc_getAssociatedObject(self, "realClass"); SEL selector = [anInvocation selector]; objc_property_t property = class_getPropertyWithSetter(realClass, selector); if (NULL != property) { NSLog(@"changing %s", property_getName(property)); } ! } Class currentClass = [self class]; object_setClass(self, realClass); [anInvocation invoke]; object_setClass(self, currentClass); ! - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { Class realClass = objc_getAssociatedObject(self, "realClass"); NSMethodSignature *sig = [realClass instanceMethodSignatureForSelector:sel]; return signature; } ! @end
  • 22. Example 2 Get outlets and actions runtime
  • 24. @interface UIRuntimeConnection : NSObject <NSCoding> ! @property (nonatomic, strong) id destination; @property (nonatomic, strong) NSString *label; @property (nonatomic, strong) id source; ! - (void)connect; - (void)connectForSimulator; ! @end ! @interface UIRuntimeEventConnection : UIRuntimeConnection ! @property (nonatomic, readonly) SEL action; @property (nonatomic, assign) UIControlEvents eventMask; @property (nonatomic, readonly) id target; ! @end ! @interface UIRuntimeOutletConnection : UIRuntimeConnection @end
  • 25. kennytm https://github.com/kennytm/iphone-private-frameworks class-dump-z https://code.google.com/p/networkpx/wiki/class_dump_z runtime Class *objc_copyClassList(unsigned int *outCount) Protocol * __unsafe_unretained *objc_copyProtocolList(unsigned int *outCount) Ivar *class_copyIvarList(Class cls, unsigned int *outCount) Method *class_copyMethodList(Class cls, unsigned int *outCount) Protocol * __unsafe_unretained *class_copyProtocolList(Class cls, unsigned int *outCount) objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
  • 26. SEL selector = NSSelectorFromString(@"initWithCoder:"); ! Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection"); Method outletMethod = class_getInstanceMethod(outletClass, selector); method_swizzle(outletMethod, ...); ! Class eventClass = NSClassFromString(@"UIRuntimeEventConnection"); Method eventMethod = class_getInstanceMethod(eventClass, selector); method_swizzle(eventMethod, ...) NO! Why not?.. Looks good.
  • 27. SEL selector = NSSelectorFromString(@"initWithCoder:"); ! Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection"); Method outletMethod = class_getInstanceMethod(outletClass, selector); ! Class eventClass = NSClassFromString(@"UIRuntimeEventConnection"); Method eventMethod = class_getInstanceMethod(eventClass, selector); ! Class baseClass = NSClassFromString(@"UIRuntimeConnection"); Method baseMethod = class_getInstanceMethod(baseClass, selector); ! baseMethod == outletMethod baseMethod != eventMethod @implementation UIRuntimeEventConnection ! - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { // decode eventMask } return self; } ! @end
  • 28. Copy method before swizzling SEL selector = NSSelectorFromString(@"initWithCoder:"); ! Class baseClass = NSClassFromString(@"UIRuntimeConnection"); Method baseMethod = class_getInstanceMethod(baseClass, selector); ! Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection"); class_addMethod(outletClass, selector, method_getImplementation(baseMethod), method_getTypeEncoding(baseMethod)); ! Method outletMethod = class_getInstanceMethod(outletClass, selector); ! method_swizzle(outletMethod, ...);
  • 29. Be a man! SEL selector = NSSelectorFromString(@"initWithCoder:"); ! Class baseClass = NSClassFromString(@"UIRuntimeConnection"); Method baseMethod = class_getInstanceMethod(baseClass, selector); ! Class outletClass = NSClassFromString(@"UIRuntimeOutletConnection"); ! id(^initWithCoderBlock)(id, id) = ^id(id aSelf, id aDecoder) { struct objc_super _super = { .receiver = aSelf, .super_class = [[aSelf class] superclass] }; ! return objc_msgSendSuper(&_super, selector, aDecoder); }; IMP initWithCoderImp = imp_implementationWithBlock(initWithCoderBlock); ! class_addMethod(outletClass, selector, initWithCoderImp, method_getTypeEncoding(baseMethod));
  • 30. Output UIStoryboardScene got ELViewController *sceneViewController ELViewController got UIStoryboard *storyboard UIControlEventTouchUpInside -[ELViewController buttonTap:(UIButton *)] UIControlEventEditingChanged -[ELViewController datePickerEditingChanged:(UIDatePicker *)] UITableView got ELViewController *dataSource ELViewController got UIDatePicker *datePicker UITableView got ELViewController *delegate ELViewController got UILabel *label ELViewController got UIView *view
  • 31. Useful links • • • • • • • Property introspection imp_implementationWithBlock class loading and initialization let's build objc_msgSend objc_msgSend ARM assembly private frameworks Objective-C Runtime Programming Guide