Runtime runtime for short. OC is the run-time mechanism, a number of mechanisms at run time, the most important of which is the message mechanism. In C, function calls determine which function is called at compile time. As for the function of OC, it is a dynamic call process. It cannot determine which function to call during compilation, and only finds the corresponding function to call according to the name of the function when it is really running. It turns out that at compile time, OC can call any function, even if the function is not implemented, as long as it is declared without an error. At compile time, C calls to unimplemented functions generate an error.

The essence of a method call is to tell an object to send a message. Objc_msgSend, only objects can send messages, so it starts with objc. To use the message mechanism, you must import #import <objc/message.h> The message mechanism is simple to use

Person *p = [[person alloc] init]; // Call the object method [p eat]; Objc_msgSend (p, @selector(eat)); Person eat = Person eat = Person eat = Person eat [[Person class] eat]; Objc_msgSend ([Person class], @selector(eat));

Message mechanism principle: object according to method number SEL to map table to find the corresponding method implementation

2. Application scenario of exchange method development: The functions of the system’s own methods are not enough, so extend some functions to the system’s own methods and keep the original functions. Method 1: inherit the system class, rewrite the method. Method 2: Use runtime and switch methods.

@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; ImageNamed = imageNamed = imageNamed = imageNamed = imageNamed + (instanceType)imageWithName:(NSString *)name; // Step 2: Swap the implementation of imageNamed and imageWithName to call imageWithName and indirectly call the implementation of imageWithName. UIImage *image = [UIImage imageNamed:@”123″]; }@end@implementation UIImage (Image)// Call + (void)load{// swap Method // get imageWithName Method address imageWithName = class_getClassMethod(self, @selector(imageWithName:)); ImageName = class_getClassMethod(self, @selector(imageNamed)); // Swap method addresses, equivalent to swap implementations method_exchangeImplementations(imageWithName, imageName); }// The system method imageNamed cannot be overridden in the class because it overwrites the system’s functionality. + (instancetype)imageWithName:(NSString *)name{// call imageWithName, ImageName UIImage *image = [self imageWithName:name]; If (image == nil) {NSLog(@” load empty image “); } return image; }@end

Principle of exchange: Before exchange:

After the exchange:

3. Application scenario of dynamically adding methods: If a class has many methods, it consumes resources when loading the class into the memory and needs to generate a mapping table for each method, you can dynamically add methods to a class to solve the problem. The classic interview question: do you use performSelector, but the main question is have you ever added a method dynamically? Simple to use

@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. Person p = [[Person alloc] init]; // The default person, which does not implement the eat method, can be called via performSelector, but will report an error. [p performSelector:@selector(eat)]; }@end@implementation Person// void()()// Default methods have two implicit arguments, void eat(id self,SEL sel){ NSLog(@”%@ %@”,self,NSStringFromSelector(sel)); }// When an object calls an unimplemented method, the method will be called and the corresponding method list will be passed. ResolveInstanceMethod :(SEL) SEL {if (SEL == @selector(eat)) {resolveInstanceMethod:(SEL) SEL {if (SEL == @selector(eat)) { Which class to add a method to // The second argument: the method number to add the method // the third argument: the function implementation to add the method (function address) // the fourth argument: V :void @: object ->self: SEL->_cmd class_addMethod(self, @selector(eat), eat, “v@:”); } return [super resolveInstanceMethod:sel]; }@end

Principle: To declare an attribute for a class is to add an association to the class, not to add the value of the memory space to the class storage space.

@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, NSObject *objc = [[NSObject alloc] init]; Objc. name = @” “; NSLog(@”%@”,objc.name); }@end// define the associated keystatic const char *key = “name”; @implementation NSObject (Property)- (NSString *)name{// Obtain the associated value based on the associated key. return objc_getAssociatedObject(self, key); }- (void)setName:(NSString *)name{ Objc_setAssociatedObject (self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }@end

5. Dictionary to model design model: The first step of dictionary to model is model attributes, which usually need to correspond with the keys in the dictionary one by one. Requirement: can automatically generate corresponding attributes from a dictionary. Solution: Provide a classification that specifically generates the corresponding attribute string according to the dictionary.

@implementation NSObject (Log)// automatic print attribute string + (void)resolveDict:(NSDictionary *)dict{// join attribute string code NSMutableString *strM = [NSMutableString string]; // 1. Go through the dictionary and get all the keys in the dictionary. Generate the corresponding attribute code [dict enumerateKeysAndObjectsUsingBlock: ^ (id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {/ / type often change, Draw out nsstrings * type; the if ([obj isKindOfClass: NSClassFromString (@ “__NSCFString”)]) {type = @ “nsstrings”; }else if ([obj isKindOfClass:NSClassFromString(@”__NSCFArray”)]){ type = @”NSArray”; }else if ([obj isKindOfClass:NSClassFromString(@”__NSCFNumber”)]){ type = @”int”; }else if ([obj isKindOfClass:NSClassFromString(@”__NSCFDictionary”)]){ type = @”NSDictionary”; } // Attribute string NSString * STR; if ([type containsString:@”NS”]) { str = [NSString stringWithFormat:@”@property (nonatomic, strong) %@ *%@;”,type,key]; }else{STR = [NSString stringWithFormat:@”@property (nonatomic, assign) %@ %@;”,type,key];} [strM appendFormat:@”\n%@\n”,str]; }]; // Print the concatenated string. NSLog(@”%@”,strM); }@end

Dictionary to model way 1: KVC

@implementation Status+ (instancetype)statusWithDict:(NSDictionary *)dict{ Status *status = [[self alloc] init]; [status setValuesForKeysWithDictionary:dict]; return status; }@end

Disadvantages of KVC dictionary to model: it is necessary to ensure that the attributes in the model correspond to the keys in the dictionary. If not consistent, is called [< Status 0 x7fa74b545d60 > setValue: forUndefinedKey:] the key to find fault. Analysis: the model of the property and the dictionary is not corresponding to different key system is called setValue: forUndefinedKey: error. Solution: rewrite object setValue: forUndefinedKey:, the method of the system, can continue to use KVC, turn the dictionary model.

  • (void)setValue:(id)value forUndefinedKey:(NSString *)key{}

The Runtime is used to iterate over all the attributes in the model. According to the attribute name of the model, search for the key in the dictionary, extract the corresponding value, and assign values to the attributes of the model. Step: Provide an NSObject class that is dedicated to dictionary models, and all future models can be translated through this class.

@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, NSString *filePath = [[NSBundle mainBundle] pathForResource:@”status.plist” ofType:nil]; NSDictionary *statusDict = [NSDictionary dictionaryWithContentsOfFile:filePath]; NSArray *dictArr = statusDict[@”statuses”]; // [NSObject resolveDict:dictArr[0][@”user”]]; _statuses = [NSMutableArray array]; For (NSDictionary *dict in dictArr) {Status * Status = [Status modelWithDict:dict]; [_statuses addObject:status]; } / / test data NSLog (@ “% @ % @”, _statuses, [_statuses [0] user]); }@end@implementation NSObject (Model)+ (instanceType)modelWithDict:(NSDictionary *)dict{// Objc = [[self alloc] init]; // class_copyIvarList: get all member attributes of the class // Ivar: get all member attributes of the class // second parameter: Ivar: indicates how many member attributes the class has. If you pass in the address of an Int variable, it will automatically assign a value to the variable. / Ivar Ivar; Ivar ivar1; Ivar ivar2; Ivar a[] = {ivar,ivar1,ivar2}; Ivar *ivarList = a; Ivar *ivarList = a; IvarList [0]; ivarList[0]; */ unsigned int count; Ivar *ivarList = class_copyIvarList(self, &count); for (int i = 0; i < count; Ivar = ivarList[I]; Ivar = ivarList[I]; / / get member attribute name nsstrings * name = [nsstrings stringWithUTF8String: ivar_getName (ivar)]; NSString *key = [name substringFromIndex:1]; Value id value = dict[key]; // If there are dictionaries in the dictionary, If ([value isKindOfClass:[NSDictionary class]]) {if ([value isKindOfClass:[NSDictionary class]]) {if ([value isKindOfClass:[NSDictionary class]]) { The class name that calls modelWithDict // is known, Is the type/member attribute/get member attribute types nsstrings * type = [nsstrings stringWithUTF8String: ivar_getTypeEncoding (ivar)]; NSRange = [type rangeOfString:@”””]; NSRange = [type rangeOfString:@”””]; NSRange = [type rangeOfString:@””]; type = [type substringFromIndex:range.location + range.length]; range = [type rangeOfString:@”””]; / / tailoring to which corner mark, not including the current Angle of standard type = [type substringToIndex: range. The location]; Class modelClass = NSClassFromString(type); If (modelClass) {value = [modelClass modelWithDict:value]; }} // NSArray is also a dictionary, If ([value isKindOfClass:[NSArray class]]) {// If ([value isKindOfClass:[NSArray class]]) {// If ([value isKindOfClass:[NSArray class]]) RespondsToSelector :@selector(arrayContainModelClass)]) {respondsToSelector:@selector(arrayContainModelClass)]; NSString *type = [idSelf arrayContainModelClass][key]; Class classModel = NSClassFromString(type); NSMutableArray *arrM = [NSMutableArray array]; For (NSDictionary *dict in value) {// id model = [classModel modelWithDict:dict]; [arrM addObject:model]; } // Assign the model array to value value = arrM; }} if (value) {objc setValue:value forKey:key]; } } return objc; }@end

Wen/Yuan Zheng Seemygo (Jane) the original links: http://www.jianshu.com/p/e071206103a4 copyright owned by the author, reproduced please contact the author for authorization, and mark “Jane book author”.