Runtime

Objective-C 

Objective-C Objective-C Objc Runtime Objc Runtime Runtime C C 

Runtime 

  1. C C runtime
  2. [object doSomething] (object) (doSomething) runtime

Objective-C runtime Modern runtime Legacy runtime Modern Runtime 64 Mac OS X Apps iOS Apps Legacy Runtime 32 Mac OS X Apps 

runtime Runtime 

 

Class 

Objective-C Class objc_class typedef struct objc_class *Class; 

objc/runtime.h objc_class struct objc_class { 

  

  

Search 

     

 

Navigate...  Navigate... 

 

Navigate... 

      

    Class isa  OBJC_ISA_AVAILABILITY;

#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

} OBJC2_UNAVAILABLE;

                    

OBJC2_UNAVAILABLE; //
OBJC2_UNAVAILABLE; //
OBJC2_UNAVAILABLE; // 0 OBJC2_UNAVAILABLE; // OBJC2_UNAVAILABLE; // OBJC2_UNAVAILABLE; // OBJC2_UNAVAILABLE; // OBJC2_UNAVAILABLE; // 

OBJC2_UNAVAILABLE; // 

  1. isa Objective-C Class isa metaClass( )
  2. super_class ( NSObject NSProxy) super_class NULL
  3. cache isa
    methodLists cache cache runtime cache cache methodLists

4. version cache 

NSArray *array = [[NSArray alloc] init];

 

  1. [NSArray alloc] NSArray +alloc NSObject
  2. NSObject +alloc NSArray isa NSArray
    +alloc cache
  3. -init NSArray cache
  4. [[NSArray alloc] init] cache

objc_objectid objc_object (objc/objc.h) 

struct objc_object {

    Class isa  OBJC_ISA_AVAILABILITY;

};

typedef struct objc_object *id;

isa Objective-C isa Runtime selector 

objc_object NSObject alloc allocWithZone: class_createInstance objc_object 

id objc_object C++ C void * 

objc_cache 

objc_class cache objc_cache 

struct objc_cache {

    unsigned int mask /* total = mask + 1 */

    unsigned int occupied

    Method buckets[1]

}; 

            

OBJC2_UNAVAILABLE;

OBJC2_UNAVAILABLE;

OBJC2_UNAVAILABLE;

  1. mask bucket Objective-C runtime selector AND (index = (mask & selector)) hash
  2. occupied bucket
  3. buckets Method mask+1 NULL bucket
    bucket

(Meta Class) 

( ) NSArray *array = [NSArray array]; 

+array NSArray NSArray objc_object isa isa +array isa objc_class meta-class 

meta-class runtime meta-class 

meta-class meta-class 

meta-class isa Objective-C meta-class isa meta-class NSObject meta-class NSObject meta-class meta-class isa 

objc_class super_class meta-class 

 

NSObject meta-class meta-class 

void TestMetaClass(id self, SEL _cmd) {

    NSLog(@"This objcet is %p", self);

    NSLog(@"Class is %@, super class is %@", [self class], [self superclass]);

    Class currentClass = [self class];

    for (int i = 0; i < 4; i++) {

        NSLog(@"Following the isa pointer %d times gives %p", i, currentClass);

        currentClass = objc_getClass((__bridge void *)currentClass);

    }

    NSLog(@"NSObject's class is %p", [NSObject class]);

    NSLog(@"NSObject's meta class is %p", objc_getClass((__bridge void *)[NSObject class]));

}

#pragma mark -

@implementation Test

- (void)ex_registerClassPair {

    Class newClass = objc_allocateClassPair([NSError class], "TestClass", 0);

    class_addMethod(newClass, @selector(testMetaClass), (IMP)TestMetaClass, "v@:");

    objc_registerClassPair(newClass);

    id instance = [[newClass alloc] initWithDomain:@"some domain" code:0 userInfo:nil];

    [instance performSelector:@selector(testMetaClass)];

}

@end 

NSError TestClass testMetaClass TestMetaClass 

2014-10-20 22:57:07.352 mountain[1303:41490] This objcet is 0x7a6e22b0

2014-10-20 22:57:07.353 mountain[1303:41490] Class is TestStringClass, super class is NSError

2014-10-20 22:57:07.353 mountain[1303:41490] Following the isa pointer 0 times gives 0x7a6e21b0

2014-10-20 22:57:07.353 mountain[1303:41490] Following the isa pointer 1 times gives 0x0

2014-10-20 22:57:07.353 mountain[1303:41490] Following the isa pointer 2 times gives 0x0

2014-10-20 22:57:07.353 mountain[1303:41490] Following the isa pointer 3 times gives 0x0

2014-10-20 22:57:07.353 mountain[1303:41490] NSObject's class is 0xe10000

2014-10-20 22:57:07.354 mountain[1303:41490] NSObject's meta class is 0x0

for objc_getClass isa NSObject meta-class 0x0 NSObject meta-class 

class meta-class 

runtime class objc object_ 

 

objc_class runtime 

(name) 

//
const char * class_getName ( Class cls ); 

class_getName cls Nil (super_class)(meta-class) 

              

//
Class class_getSuperclass ( Class cls ); 

// Class
BOOL class_isMetaClass ( Class cls ); 

class_getSuperclass cls Nil cls Nil NSObject superclass class_isMetaClass cls YES cls Nil NO 

(instance_size) 

//
size_t class_getInstanceSize ( Class cls ); 

(ivars)objc_class ivars ivars Ivar( ) runtime 

1. 

//
Ivar class_getInstanceVariable ( Class cls, const char *name ); 

//
Ivar class_getClassVariable ( Class cls, const char *name ); 

//
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ); 

//
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount ); 

class_getInstanceVariable name objc_ivar (Ivar) class_getClassVariable Objective-C Objective-C 

 

Objective-C class_addIvar objc_allocateClassPair objc_registerClassPair 1<<alignment ivar log2(sizeof(pointer_type)) 

class_copyIvarList objc_ivar outCount free() 

2. // 

objc_property_t class_getProperty ( Class cls, const char *name );

//
objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount ); 

//
BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount ); 

//
void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount ); 

ivars 

3. MAC OS X runtime strong/weak 

const uint8_t * class_getIvarLayout ( Class cls );

void class_setIvarLayout ( Class cls, const uint8_t *layout );

const uint8_t * class_getWeakIvarLayout ( Class cls );

void class_setWeakIvarLayout ( Class cls, const uint8_t *layout );

objc_registerClassPair (methodLists) 

            

//
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types ); 

//
Method class_getInstanceMethod ( Class cls, SEL name ); 

//
Method class_getClassMethod ( Class cls, SEL name ); 

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

//
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types ); 

//
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name ); 

// selector
BOOL class_respondsToSelector ( Class cls, SEL sel ); 

class_addMethod NO method_setImplementation Objective-C C —self _cmd (IMP ) 

void myMethodIMP(id self, SEL _cmd)

{

    // implementation ....

}

                                  

types 

class_getInstanceMethod class_getClassMethod class_copyMethodList 

class_copyMethodList class_copyMethodList(object_getClass(cls), &count)( ) outCount free() 

class_replaceMethod name class_addMethod name method_setImplementation 

class_getMethodImplementation method_getImplementation(class_getInstanceMethod(cls, name)) runtime selector 

class_respondsToSelector NSObject respondsToSelector: instancesRespondToSelector: (objc_protocol_list) 

              

//
BOOL class_addProtocol ( Class cls, Protocol *protocol ); 

//
BOOL class_conformsToProtocol ( Class cls, Protocol *protocol ); 

//
Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount ); 

class_conformsToProtocol NSObject conformsToProtocol: class_copyProtocolList free() 

(version) 

//
int class_getVersion ( Class cls ); 

//
void class_setVersion ( Class cls, int version ); 

 

runtime CoreFoundation tool-free bridging Class objc_getFutureClass ( const char *name ); 

void objc_setFutureClass ( Class cls, const char *name );

               

(Example) 

//-----------------------------------------------------------

// MyClass.h

@interface MyClass : NSObject <NSCopying, NSCoding>

@property (nonatomic, strong) NSArray *array;

@property (nonatomic, copy) NSString *string;

- (void)method1;

- (void)method2;

+ (void)classMethod1;

@end 

//-----------------------------------------------------------

// MyClass.m

#import "MyClass.h"

@interface MyClass () {

    NSInteger       _instance1;

    NSString    *   _instance2;

}

@property (nonatomic, assign) NSUInteger integer;

- (void)method3WithArg1:(NSInteger)arg1 arg2:(NSString *)arg2;

@end

@implementation MyClass

+ (void)classMethod1 {

}

- (void)method1 {

    NSLog(@"call method method1");

}

- (void)method2 {

}

- (void)method3WithArg1:(NSInteger)arg1 arg2:(NSString *)arg2 {

    NSLog(@"arg1 : %ld, arg2 : %@", arg1, arg2);

}

@end 

//-----------------------------------------------------------

// main.h

#import "MyClass.h"

#import "MySubClass.h"

#import <objc/runtime.h>

int main(int argc, const char * argv[]) {

    @autoreleasepool {

        MyClass *myClass = [[MyClass alloc] init];

        unsigned int outCount = 0;

        Class cls = myClass.class;

//
NSLog(@"class name: %s", class_getName(cls)); 

        NSLog(@"==========================================================");

//
NSLog(@"super class name: %s", class_getName(class_getSuperclass(cls))); NSLog(@"=========================================================="); 

//
NSLog(@"MyClass is %@ a meta-class", (class_isMetaClass(cls) ? @"" : @"not")); NSLog(@"=========================================================="); 

        Class meta_class = objc_getMetaClass(class_getName(cls));

        NSLog(@"%s's meta-class is %s", class_getName(cls), class_getName(meta_class));

        NSLog(@"==========================================================");

//
NSLog(@"instance size: %zu", class_getInstanceSize(cls)); NSLog(@"=========================================================="); 

//
Ivar *ivars = class_copyIvarList(cls, &outCount); for (int i = 0; i < outCount; i++) { 

            Ivar ivar = ivars[i];

            NSLog(@"instance variable's name: %s at index: %d", ivar_getName(ivar), i);

        }

        free(ivars);

        Ivar string = class_getInstanceVariable(cls, "_string");

        if (string != NULL) {

            NSLog(@"instace variable %s", ivar_getName(string));

        }

        NSLog(@"==========================================================");

//
objc_property_t * properties = class_copyPropertyList(cls, &outCount); for (int i = 0; i < outCount; i++) { 

            objc_property_t property = properties[i];

            NSLog(@"property's name: %s", property_getName(property));

        }

        free(properties);

        objc_property_t array = class_getProperty(cls, "array");

        if (array != NULL) {

            NSLog(@"property %s", property_getName(array));

        }

        NSLog(@"==========================================================");

//
Method *methods = class_copyMethodList(cls, &outCount); for (int i = 0; i < outCount; i++) { 

            Method method = methods[i];

            NSLog(@"method's signature: %s", method_getName(method));

        }

        free(methods);

        Method method1 = class_getInstanceMethod(cls, @selector(method1));

        if (method1 != NULL) {

            NSLog(@"method %s", method_getName(method1));

        }

        Method classMethod = class_getClassMethod(cls, @selector(classMethod1));

        if (classMethod != NULL) {

            NSLog(@"class method : %s", method_getName(classMethod));

        }

        NSLog(@"MyClass is%@ responsd to selector: method3WithArg1:arg2:", class_respondsToSelector(cls, @selector(method3WithArg1:arg2:)) ? @

        IMP imp = class_getMethodImplementation(cls, @selector(method1));

        imp();

        NSLog(@"==========================================================");

//
Protocol * __unsafe_unretained * protocols = class_copyProtocolList(cls, &outCount); Protocol * protocol;
for (int i = 0; i < outCount; i++) { 

            protocol = protocols[i];

            NSLog(@"protocol name: %s", protocol_getName(protocol));

        }

        NSLog(@"MyClass is%@ responsed to protocol %s", class_conformsToProtocol(cls, protocol) ? @"" : @" not", protocol_getName(protocol));

        NSLog(@"==========================================================");

    }

return 0; } 

 

2014-10-22 19:41:37.452 RuntimeTest[3189:156810] class name: MyClass

2014-10-22 19:41:37.453 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.454 RuntimeTest[3189:156810] super class name: NSObject

2014-10-22 19:41:37.454 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.454 RuntimeTest[3189:156810] MyClass is not a meta-class

2014-10-22 19:41:37.454 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.454 RuntimeTest[3189:156810] MyClass's meta-class is MyClass

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance size: 48

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _instance1 at index: 0

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _instance2 at index: 1

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _array at index: 2

2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _string at index: 3

2014-10-22 19:41:37.463 RuntimeTest[3189:156810] instance variable's name: _integer at index: 4

2014-10-22 19:41:37.463 RuntimeTest[3189:156810] instace variable _string

2014-10-22 19:41:37.463 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.463 RuntimeTest[3189:156810] property's name: array

2014-10-22 19:41:37.463 RuntimeTest[3189:156810] property's name: string

2014-10-22 19:41:37.464 RuntimeTest[3189:156810] property's name: integer

2014-10-22 19:41:37.464 RuntimeTest[3189:156810] property array

2014-10-22 19:41:37.464 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method1

2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method2

2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method3WithArg1:arg2:

2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: integer

2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setInteger:

2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: array

2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: string

2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setString:

2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setArray:

2014-10-22 19:41:37.466 RuntimeTest[3189:156810] method's signature: .cxx_destruct

2014-10-22 19:41:37.466 RuntimeTest[3189:156810] method method1

2014-10-22 19:41:37.466 RuntimeTest[3189:156810] class method : classMethod1

2014-10-22 19:41:37.466 RuntimeTest[3189:156810] MyClass is responsd to selector: method3WithArg1:arg2:

2014-10-22 19:41:37.467 RuntimeTest[3189:156810] call method method1

2014-10-22 19:41:37.467 RuntimeTest[3189:156810] ==========================================================

2014-10-22 19:41:37.467 RuntimeTest[3189:156810] protocol name: NSCopying

2014-10-22 19:41:37.467 RuntimeTest[3189:156810] protocol name: NSCoding

2014-10-22 19:41:37.467 RuntimeTest[3189:156810] MyClass is responsed to protocol NSCoding

2014-10-22 19:41:37.468 RuntimeTest[3189:156810] ==========================================================

 

runtime 

 

               

//
Class objc_allocateClassPair ( Class superclass, const char *name, size_t extraBytes ); 

//
void objc_disposeClassPair ( Class cls ); 

// objc_allocateClassPair void objc_registerClassPair ( Class cls ); 

objc_allocateClassPair superclass Nil extraBytes 0 ivars 

objc_allocateClassPair class_addMethod class_addIvar objc_registerClassPair 

objc_disposeClassPair 

                                             

Class cls = objc_allocateClassPair(MyClass.class, "MySubClass", 0);

class_addMethod(cls, @selector(submethod1), (IMP)imp_submethod1, "v@:");

class_replaceMethod(cls, @selector(method1), (IMP)imp_submethod1, "v@:");

class_addIvar(cls, "_ivar1", sizeof(NSString *), log(sizeof(NSString *)), "i");

objc_property_attribute_t type = {"T", "@"NSString""};

objc_property_attribute_t ownership = { "C", "" };

objc_property_attribute_t backingivar = { "V", "_ivar1"};

objc_property_attribute_t attrs[] = {type, ownership, backingivar};

class_addProperty(cls, "property2", attrs, 3);

objc_registerClassPair(cls);

id instance = [[cls alloc] init];

[instance performSelector:@selector(submethod1)];

[instance performSelector:@selector(method1)];

 

2014-10-23 11:35:31.006 RuntimeTest[3800:66152] run sub method 1

2014-10-23 11:35:31.006 RuntimeTest[3800:66152] run sub method 1

 

            

//
id class_createInstance ( Class cls, size_t extraBytes ); 

//
id objc_constructInstance ( Class cls, void *bytes ); 

//
void * objc_destructInstance ( id obj ); 

class_createInstance extraBytes ARC 

class_createInstance +alloc class_createInstance NSString 

id theObject = class_createInstance(NSString.class, sizeof(unsigned));

id str1 = [theObject init];

NSLog(@"%@", [str1 class]);

id str2 = [[NSString alloc] initWithString:@"test"];

NSLog(@"%@", [str2 class]);

 

2014-10-23 12:46:50.781 RuntimeTest[4039:89088] NSString

2014-10-23 12:46:50.781 RuntimeTest[4039:89088] __NSCFConstantString

class_createInstance NSString __NSCFConstantString objc_constructInstance (bytes) objc_destructInstance 

 

                                                                   

              

1. // 

id object_copy ( id obj, size_t size );

//
id object_dispose ( id obj ); 

A B B A B A A B B B A 

NSObject *a = [[NSObject alloc] init];

id newB = object_copy(a, class_getInstanceSize(MyClass.class));

object_setClass(newB, MyClass.class);

object_dispose(a);

2. // 

Ivar object_setInstanceVariable ( id obj, const char *name, void *value );

//
Ivar object_getInstanceVariable ( id obj, const char *name, void **outValue ); 

// void * object_getIndexedIvars ( id obj ); 

//
id object_getIvar ( id obj, Ivar ivar ); 

//
void object_setIvar ( id obj, Ivar ivar, id value ); 

Ivar object_getIvar object_getInstanceVariable object_setIvar object_setInstanceVariable 3. 

//
const char * object_getClassName ( id obj ); 

//
Class object_getClass ( id obj ); 

原文地址:https://www.cnblogs.com/eyxForWork/p/5717062.html