Objective-C Runtime Classes
Objective-many C language decisions can be executed during compilation and runtime. As long as it is possible, it is dynamic. This means that the Objective-C language requires not only a compiler, but also a runtime system to execute the compiled code. The Runtime system is an operating system used in Objective-C language. It enables the OC language to work.
The core of Runtime is dynamic operation class and message distribution to other objects at Runtime. This document mainly introduces the dynamic operation class at Runtime.
You can learn the dynamic operation class during runtime. However, in most cases, we do not need to write the relevant code of the Runtime system.
Note:In Runtime, all char * data is UTF-8 encoded.
I. Preparations 1. Import the framework objc/runtime. h
#import < objc/runtime.h >
2. User class
User. h
/// User. h // Runtime /// Created by yangjun on 15/9/21. // Copyright©June 2015. All rights reserved. // # import
/// User @ interface User: NSObject @ property (nonatomic, copy) NSString * userName; /// <userName/*** initialization ** @ param userName ** @ return id */-(id) initWithUserName :( NSString *) userName; /*** initialize ** @ param userName ** @ return id */+ (id) userWithUserName :( NSString *) userName; @ end
User. m
/// User. m // Runtime /// Created by yangjun on 15/9/21. // Copyright©June 2015. all rights reserved. // # import User. h @ implementation User + (id) userWithUserName :( NSString *) userName {User * user = [[User alloc] init]; user. userName = userName; return userName;} # pragma mark initialization-(id) initWithUserName :( NSString *) userName {self = [super init]; if (self) {self. userName = userName;} return self;} @ end
Ii. Category
1. Source Code
# Pragma mark-class-(void) testClass {// obtain class id userClass = objc_getClass (User); NSLog (@%@, userClass ); // equivalent userClass = [User class]; NSLog (@%@, userClass); // parent class fprintf (stdout, parent class); id superUserClass = class_getSuperclass (userClass ); NSLog (@ % @, superUserClass); // equivalent superUserClass = [User new]. superclass; NSLog (@ % @, superUserClass); // change the object class fprintf (stdout, change the object class); User * user = [User new]; NSLog (@ Class: % @ userName: % @, user, user. userName); userClass = object_setClass (user, [ClassTest class]); // replaces the class and returns the NSLog (@ class: % @ userName: % @, user, user. userName );}
2. Output
10:12:52. 140 Runtime [14129: 681188] User
10:12:52. 141 Runtime [14129: 681188] User
Parent class
10:12:52. 141 Runtime [14129: 681188] NSObject
10:12:52. 141 Runtime [14129: 681188] NSObject
Change the class of an object
10:12:52. 141 Runtime [14129: 681188] class: userName :( null)
10:12:52. 141 Runtime [14129: 681188] class: userName: Yang Jun
Iii. Class Name
1. Source Code
# Pragma mark-class name-(void) testName {// obtain class id userClass = objc_getClass (User); const char * className = class_getName (userClass); fprintf (stdout, class Name: % s, className); // equivalent className = object_getClassName (userClass); fprintf (stdout, Class Name: % s, className ); // equivalent OC userClass = [User class]; NSString * name = NSStringFromClass (userClass); NSLog (@ class name: % @, name ); // underlying conversion name = [NSString stringWithCString: className encoding: NSUTF8StringEncoding]; NSLog (@ Class name: % @, name );}
2. Output
Class Name: User
Class Name: User
10:14:03. 278 Runtime [14140: 681770] Class Name: User
10:14:03. 279 Runtime [14140: 681770] Class Name: User
Iv. Attributes
1. Source Code
# Pragma mark-Attribute-(void) testPropertyName {// get all attributes fprintf (stdout, get all attributes); id userClass = objc_getClass (User); unsigned int outCount, I; objc_property_t * properties = class_copyPropertyList (userClass, & outCount); // all attributes for (I = 0; I <outCount; I ++) {objc_property_t property = properties [I]; // attribute const char * propertyName = property_getName (property); // attribute name const char * propertyAttributes = property_getAttributes (property); // attribute type fprintf (stdout, % s, propertyName, propertyAttributes); // equivalent output NSLog (, [NSString stringWithCString: propertyName encoding: NSUTF8StringEncoding]);} // a single attribute fprintf (stdout, single attribute ); ivar var = class_getInstanceVariable (userClass, _ userName); const char * typeEncoding = ivar_getTypeEncoding (var); const char * ivarName = ivar_getName (var); fprintf (stdout, attribute: % s; Type: % s, ivarName, typeEncoding); // you need to disable the ARC mode fprintf (stdout, set/get the attribute value) to set/obtain the attribute value ); user * user = [[User alloc] init] autorelease]; NSString * userName = @ Yang Jun; object_setInstanceVariable (user, _ userName, userName); NSLog (@ user. userName: % @, user. userName); user. userName = @ enable ARC; // modify the value object_getInstanceVariable (user, _ userName, (void *) & userName); NSLog (@ user. userName: % @, userName );}
2. Output
Get all attributes
UserName T @ "NSString", C, N, V_userName
10:18:54. 365 Runtime [14155: 684097] userName
Single Attribute
Property name: _ userName; Type: @ "NSString"
Set/obtain attribute values
10:18:54. 366 Runtime [14155: 684097] user. userName: Yang Jun
10:18:54. 367 Runtime [14155: 684097] user. userName: Enable ARC
V. Methods
1. Source Code
Global method:
NSString * classAddMethodIMP (id self, SEL _ cmd, NSString * str) {// implementation .... NSLog (@ value: % @, str); return str;} NSString * userName (id self, SEL _ cmd) {return @ OC ;}
Local method:
# Pragma mark-method-(void) testMethod {// obtain all methods fprintf (stdout, get all methods); id userClass = objc_getClass (User); u_int count; // unsigned int Method * methods = class_copyMethodList (userClass, & count); // all methods, including only instance methods) for (int I = 0; I <count; I ++) {Method method = methods [I]; SEL name = method_getName (method); // convert to const char * selName = sel_getName (name ); // convert to the method name const char * methodTypeEncoding = method_getTypeEncoding (method); // the char * methodType = method_copyReturnType (method) of the method transmission; // The type fprintf (stdout, method Name: % s; return type % s; parameter: % s, selName, methodType, methodTypeEncoding);} // 1. extraction Method (Class Method) fprintf (stdout, method extraction); SEL name = sel_registerName (userWithUserName :); method Method = class_getClassMethod (userClass, name); name = method_getName (Method ); fprintf (stdout, extraction method (+): % s, sel_getName (name); // 2. extraction Method (instance method) name = sel_registerName (initWithUserName :); method = class_getInstanceMethod (userClass, name); name = method_getName (Method); fprintf (stdout, extraction method (-): % s, sel_getName (name); // 3. extract IMP imp = method_getImplementation (method); // you can only obtain the (-) method imp = class_getMethodImplementation (userClass, name); imp = class_getMethodImplementation_stret (userClass, name ); // equivalent User * user = [[User alloc] init]; imp = [user methodForSelector: name]; // class add method (Global Method) fprintf (stdout, class addition method); name = sel_registerName (classAddMethodIMP); BOOL addMethod = class_addMethod (userClass, name, (IMP) classAddMethodIMP, I @:@); // determine whether the class has this method. if (addMethod & class_respondsToSelector (userClass, name) & [user respondsToSelector: name]) {fprintf (stdout, class % s addition method % s succeeded, class_getName (userClass), sel_getName (name);} // class addition method (-) name = @ selector (classAddMethod :); method = class_getInstanceMethod (self. class, name); // method body imp = method_getImplementation (method); // method implementation class_addMethod (userClass, name, imp, v @:); // method call id methodBack = [user defined mselector: @ selector (classAddMethod :) withObject: @ Yang Jun]; NSLog (@ Class % @ call method % @ return: % @, NSStringFromClass (user. class), [NSString stringWithCString: sel_getName (name) encoding: NSUTF8StringEncoding], methodBack); // method exchange fprintf (stdout, method exchange ); method m1 = class_getInstanceMethod ([self class], @ selector (userName); Method m2 = class_getInstanceMethod ([self class], @ selector (userName2); method_exchangeImplementations (m1, m2); NSLog (@ % @, [self userName]); NSLog (@ % @, [self userName2]); // replace fprintf (stdout, replace method ); method userNameMethod = class_getInstanceMethod (self. class, @ selector (userName); IMP userNameImp = method_getImplementation (userNameMethod); Method setUserNameMethod = class_getInstanceMethod (self. class, @ selector (userName2); method_setImplementation (setUserNameMethod, userNameImp); NSLog (@ % @, [self userName]); NSLog (@ % @, [self userName2]); // method override. The method name must be the same as fprintf (stdout, method override); NSLog (@%@, user. userName); name = sel_registerName (userName); imp = class_replaceMethod (userClass, name, (IMP) userName, I @: @); NSLog (@ % @, user. userName) ;}# method covered by pragma mark-(NSString *) userName {return @ Yang Jun;}-(NSString *) userName2 {return @ IOS ;} # method added by pragma mark-(NSString *) classAddMethod :( NSString *) str {return str ;}
2. Output
Get all methods
Method Name: initWithUserName:; return type @; parameter: @ 24 @ 0: 8 @ 16
Method Name: userName; return type @; parameter: @ 16 @ 0: 8
Method Name: setUserName:; return type v; parameter: v24 @ 0: 8 @ 16
Method Extraction
Extraction Method (+): userWithUserName:
Extraction Method (-): initWithUserName:
Class Addition Method
ClassAddMethodIMP method added by class User
10:21:19. 167 Runtime [14182: 685354] class User call method classAddMethod: Return: Yang Jun
Method exchange
10:21:19. 168 Runtime [14182: 685354] IOS
10:21:19. 168 Runtime [14182: 685354] Yang Jun
Method replacement
10:21:19. 168 Runtime [14182: 685354] IOS
10:21:19. 168 Runtime [14182: 685354] IOS
Method coverage
10:21:19. 169 Runtime [14182: 685354] (null)
10:21:19. 169 Runtime [14182: 685354] OC