iOS runtime practical application: member variables and properties

iOS runtime practical application: member variables and properties

[[164431]]

original

Preface

Before you begin, it is recommended to read the basic understanding of iOS runtime: iOS internal skills: runtime

During an interview, a guy encountered such a question: "Do you know the nature of member variables?" The guy was immediately confused. What is the nature of member variables? Member variables are member variables. They are just used in daily life. What is the deeper meaning? This article focuses on the definition and use of member variables and properties in runtime.

Noun Analysis

Member variables

1. Definition:

Ivar: instance variable type, a pointer to the objc_ivar structure

  1. typedef struct objc_ivar *Ivar;

2. Operation function:

  1. // Get all member variables  
  2. class_copyIvarList
  1. // Get the member variable name  
  2. ivar_getName
  1. // Get the member variable with the specified name  
  2. class_getInstanceVariable
  1. // Get member variable type code  
  2. ivar_getTypeEncoding
  1. // Set the value of an object member variable  
  2. object_setIvar
  1. // Get the value of an object member variable  
  2. object_getIvar

3. Use cases:

The Model header file is declared as follows:

  1. @interface Model : NSObject {
  2. NSString *_str1;
  3. }
  4. @property NSString * str2;
  5. @property (nonatomic, copy) NSDictionary * dict1;
  6. @end  

Get its member variables:

  1. unsigned int outCount = 0 ;
  2. Ivar * ivars = class_copyIvarList([Model class ], &outCount);
  3. for (unsigned int i = 0 ; i < outCount; i ++) {
  4. Ivar ivar = ivars[i];
  5. const   char * name = ivar_getName(ivar);
  6. const   char * type = ivar_getTypeEncoding(ivar);
  7. NSLog(@ "%s of type %s" , type, name);
  8. }
  9. free(ivars);

Print results:

  1. runtimeIvar[ 602 : 16885 ] _str1 of type @ "NSString"
  2. runtimeIvar[ 602 : 16885 ] _str2 of type @ "NSString"
  3. runtimeIvar[ 602 : 16885 ] _dict1 of type @ "NSDictionary"

property

1. Definition:

objc_property_t: The type of the declared property, a pointer to the objc_property structure

  1. typedef struct objc_property *objc_property_t;

2. Operation function:

  1. // Get all properties  
  2. class_copyPropertyList

Note: Using class_copyPropertyList will not get member variables without @property declaration

  1. // Get the attribute description string  
  2. property_getAttributes
  1. // Get the attribute name  
  2. property_getName
  1. // Get all attribute properties  
  2. property_copyAttributeList

illustrate:

The property_getAttributes function returns a list of objc_property_attribute_t structures. The objc_property_attribute_t structure contains name and value. The commonly used attributes are as follows:

  1. Property Type name value: T value: varies
  2. Encoding type name value: C (copy) & (strong) W (weak) empty (assign) etc. value: None
  3. Non/atomic name value: empty (atomic) N (Nonatomic) value: none
  4. Variable name name value: V value: changes

The description obtained using property_getAttributes is a general description of all the names and values ​​that property_copyAttributeList can obtain, such as T@"NSDictionary",C,N,V_dict1

3. Use cases:

  1. unsigned int outCount = 0 ;
  2. objc_property_t * properties = class_copyPropertyList([Model class ], &outCount);
  3. for (unsigned int i = 0 ; i < outCount; i ++) {
  4. objc_property_t property = properties[i];
  5. //Attribute name  
  6. const   char * name = property_getName(property);
  7. //Attribute description  
  8. const   char * propertyAttr = property_getAttributes(property);
  9. NSLog(@ "%s with property description %s" , propertyAttr, name);
  10.           
  11. //Attribute characteristics  
  12. unsigned int attrCount = 0 ;
  13. objc_property_attribute_t * attrs = property_copyAttributeList(property, &attrCount);
  14. for (unsigned int j = 0 ; j < attrCount; j ++) {
  15. objc_property_attribute_t attr = attrs[j];
  16. const   char * name = attr.name;
  17. const   char * value = attr.value;
  18. NSLog(@ "Property description: %s Value: %s" , name, value);
  19. }
  20. free(attrs);
  21. NSLog(@ "\n" );
  22. }
  23. free(properties);

Print results:

  1. runtimeIvar[ 661 : 27041 ] str2 with property description T@ "NSString" ,&,V_str2
  2. runtimeIvar[ 661 : 27041 ] Property description: T Value: @ "NSString"  
  3. runtimeIvar[ 661 : 27041 ] Property Description: & Value:
  4. runtimeIvar[ 661 : 27041 ] Property Description: V Value: _str2
  5. runtimeIvar[ 661 : 27041 ]
  6. runtimeIvar[ 661 : 27041 ] dict1 with attribute description T@ "NSDictionary" ,C,N,V_dict1
  7. runtimeIvar[ 661 : 27041 ] Property Description: T Value: @ "NSDictionary"  
  8. runtimeIvar[ 661 : 27041 ] Property Description: C Value:
  9. runtimeIvar[ 661 : 27041 ] Property Description: N Value:
  10. runtimeIvar[ 661 : 27041 ] Property Description: V Value: _dict1
  11. runtimeIvar[ 661 : 27041 ]

Application Examples

1. Conversion from Json to Model

In development, I believe the most common thing is that interface data needs to be converted into Model (of course, if you take values ​​directly from Dict...), many developers also use well-known third-party libraries such as JsonModel, Mantle or MJExtension, etc. If you only use them without knowing why, it is really no different from "moving bricks". Next, we use runtime to parse json to assign values ​​to the Model.

Principle description: Use the function provided by runtime to traverse all attributes of the Model itself. If the attribute has a corresponding value in json, assign it.

Core method: Add method to NSObject category:

  1. - (instancetype)initWithDict:(NSDictionary *)dict {
  2.   
  3. if (self = [self init]) {
  4. //(1) Get the attributes of the class and the corresponding types of the attributes  
  5. NSMutableArray * keys = [NSMutableArray array];
  6. NSMutableArray * attributes = [NSMutableArray array];
  7. /*
  8. * example
  9. * name = value3 attribute = T@"NSString",C,N,V_value3
  10. * name = value4 attribute = T^i,N,V_value4
  11. */  
  12. unsigned int outCount;
  13. objc_property_t * properties = class_copyPropertyList([self class ], &outCount);
  14. for ( int i = 0 ; i < outCount; i ++) {
  15. objc_property_t property = properties[i];
  16. //Get the name of the property through the property_getName function  
  17. NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
  18. [keys addObject:propertyName];
  19. //The property name and @encode encoding can be obtained through the property_getAttributes function  
  20. NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
  21. [attributes addObject:propertyAttribute];
  22. }
  23. //Immediately release the memory pointed to by properties  
  24. free(properties);
  25.   
  26. //(2) Assign values ​​to attributes according to type  
  27. for (NSString * key in keys) {
  28. if ([dict valueForKey:key] == nil) continue ;
  29. [self setValue:[dict valueForKey:key] forKey:key];
  30. }
  31. }
  32. return self;
  33.   
  34. }

Readers can further think about:

  • How to identify and process the properties of basic data types

  • Handling of empty (nil, null) values

  • Processing of nested json (Dict or Array) in json

Try to solve the above problems, and you can also write your own full-featured Json to Model library.

2. Quick Archiving

Sometimes we need to archive some information, such as the user information class UserInfo, which will require overriding the initWithCoder and encodeWithCoder methods, and performing encode and decode operations on each attribute. Then the question is: when there are only a few attributes, it can be easily written, but what if there are dozens of attributes? Wouldn't it take forever to write? . . .

Principle description: Use the function provided by runtime to traverse all attributes of the Model itself, and encode and decode the attributes.

Core method: Override the method in the base class of Model:

  1. - (id)initWithCoder:(NSCoder *)aDecoder {
  2. if (self = [ super init]) {
  3. unsigned int outCount;
  4. Ivar * ivars = class_copyIvarList([self class ], &outCount);
  5. for ( int i = 0 ; i < outCount; i ++) {
  6. Ivar ivar = ivars[i];
  7. NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)];
  8. [self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
  9. }
  10. }
  11. return self;
  12. }
  13.   
  14. - ( void )encodeWithCoder:(NSCoder *)aCoder {
  15. unsigned int outCount;
  16. Ivar * ivars = class_copyIvarList([self class ], &outCount);
  17. for ( int i = 0 ; i < outCount; i ++) {
  18. Ivar ivar = ivars[i];
  19. NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)];
  20. [aCoder encodeObject:[self valueForKey:key] forKey:key];
  21. }
  22. }

3. Accessing private variables

We know that there are no real private variables and methods in OC. To make member variables private, they must be declared in the m file and not exposed to the outside world. If we know the name of the member variable, we can get the member variable through runtime and then get its value through getIvar.

method:

  1. Ivar ivar = class_getInstanceVariable([Model class ], "_str1" );
  2. NSString * str1 = object_getIvar(model, ivar);

Everyone is welcome to communicate and discuss.

<<:  Let's take a look at iOS local persistent storage (focusing on the SQLite database)

>>:  Comprehensive analysis of Activity startup mode

Recommend

Lessons on how to make money that ordinary people can implement

Course List Lesson 1-The relationship between bac...

Zheng Xiangzhou-New Business Model Complete Works Value 12980

Zheng Xiangzhou-New Business Model Complete Works...

2 tips to double your conversion rate! Which one have you used?

In previous articles, Qingguajun has always empha...

Digital camera sales hit a new low, replaced by smartphones

Last month, the Camera and Imaging Products Associ...

How to Develop the Next Generation of Highly Secure Apps

[[164448]] One of the great benefits of the mobil...

How much does it cost to customize a travel agency mini program in Sanya?

What is the price for customizing the Sanya Trave...

Hmm? Have I been spelling “嗯” wrong for so many years?

In daily life and chatting, the word "嗯"...