A preface to the reflection mechanism of objective-c from the perspective of Jsonmodel
In the era of mobile interconnection, JSON is almost ubiquitous as a data transmission format. As an iOS developer, how do I get a string of JSON strings to handle? I think in most cases it is necessary to turn it into a custom NSObject object for reuse, and for this conversion process, most people do this:
1234567 |
... user* User=[[user alloc] init];user.userid =[json objectforkey:@"userId"];user.nick= [JSON objectforkey:@] Nick "];user.image = [json objectforkey:@" image "];user.age = [json objectforkey:@" age "]; ... |
This code is correct, but also absolutely not elegant, the more attributes in the model, the more redundant code of the corresponding more. Naturally there is a better solution to this problem, for example:
Two lines of code is enough, of course, to achieve this function, is actually put a lot of work behind the Jsonmodel this open source package to do. As for its realization principle, it is mainly based on the reflection mechanism of OBJECTIVE-C runtime.
About reflection
Thinking in Java interprets reflection as class information at run time , which is the fact that this kind of information is unknown at compile time and needs to be obtained dynamically during program run, which is the problem we tried to solve. For a JSON string obtained from a network, it is of course not known during code compilation. Although the Java language is spoken here, this reflection mechanism is also supported for OBJECTIVE-C.
Implementation in the Jsonmodel
The break point records the following sequence of method calls in this class: Jsonmodel
The acquisition of object properties is mainly in the last Inspectproperties method
Here is the code snippet for the Inspectproperties method:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
···Inspects the class, get ' s a list of the class properties-(void) __inspectproperties{Jmlog (@ "Inspect class:%@", [Self class]);nsmutabledictionary* Propertyindex = [Nsmutabledictionary dictionary];Temp variables for the loops class class = [Self class]; nsscanner* scanner =Nilnsstring* PropertyType =NilInspect inherited properties up to the Jsonmodel classwhile (Class! = [Jsonmodel class]) {Jmlog (@ "Inspecting:%@", Nsstringfromclass (Class));Unsignedint propertycount; objc_property_t *properties = Class_copypropertylist (class, &propertycount);Loop over the class propertiesfor (Unsignedint i =0; i < Propertycount; i++) {jsonmodelclassproperty* p = [[Jsonmodelclassproperty alloc] init];Get Property name objc_property_t property = Properties[i];ConstChar *propertyname = Property_getname (property); P. name = [NSString Stringwithutf8string:propertyname];Jmlog (@ "Property:%@", p.name);Get Property attributesConstChar *attrs = property_getattributes (property);nsstring* PropertyAttributes = [NSString Stringwithutf8string:attrs];if ([PropertyAttributes hasprefix:@"Tc,"]) { //mask bools as structs so they can has custom convertors p. Structname = @"BOOL";} scanner = [Nsscanner scannerwithstring:propertyattributes]; //jmlog (@ "attr:%@", [NSString stringwithcstring:attrs encoding:nsutf8stringencoding]); [Scanner scanuptostring:@"T" intostring: Nil]; [Scanner scanstring:@"T" intostring:nil]; //finally Store, index in the static property Indexobjc_setassociatedobject (self. class, & Kclasspropertieskey, [propertyindex copy], Objc_association_retain //This is atomic); |
Here you can see the basic steps below
- Gets the metadata information for the current class by calling its own class method
- The Class_copypropertylist method of the runtime gets the list of properties of the current class, returned as an array of pointers
- Iterate through the array of pointers, get the property name through Property_getname, Property_getattributes get the property type
- Using Nsscanner to scan the property type string, it will resemble the following form "[email protected]" NSNumber ", &,n,v_id", processed into NSNumber, property-by-attribute loop processing
- Put all the processed data into the Propertyindex dictionary.
- Associate this data to Kclasspropertieskey with Objc_setassociatedobject
When used in the properties method, the property data is taken out:
1234567891011121314 |
// Returns a list of the model ' s properties-(nsarray*) __properties__{// Fetch the associated object nsdictionary* classproperties = Objc_getassociatedobject (self.class, &kclasspropertieskey); if (classproperties) return [classproperties allvalues]; //if here, the class needs to inspect itself [self __setup__]; //return the property list classproperties = Objc_getassociatedobject ( Self.class, &kclasspropertieskey); return [classproperties allvalues];} |
The above is the jsonmodel of the use of reflection mechanism to achieve the Class property acquisition process, compared to the common method of value-per-assignment, this approach in the code is indeed concise and elegant, especially for the use of the class attributes more complex cases, eliminating a lot of unnecessary code.
Reflection mechanism of OBJECTIVE-C