Benefits-> KVC + Runtime: Get the attributes, member variables, methods, and protocols of classes/objects and implement dictionary-to-model conversion. kvcruntime
We know that KVC + Runtime can do a lot of things. With this, we can achieve a lot of results.
Here we provide a benefit. We use KVC + Runtime to obtain all member variables, attributes, methods, and protocols of classes/objects;
And use it to implement dictionary-to-model conversion.
If you don't talk much about it, go directly to the Code:
1. Tool class (actually a classification of NSObject) header file
1 # import <Foundation/Foundation. h> 2 3 @ interface NSObject (YSRuntime) 4 5/** 6 return the attribute array of the current Class 7 8 @ return attribute array (for example, "name", "age ", "address") 9 */10 + (NSArray *) ys_propertiesList; 11 12/** 13 return the member variable array of the current class 14 15 @ return member variable array 16 */17 + (NSArray *) ys_ivarsList; 18 19/** 20 return the object method array of the current class 21 22 @ return method array 23 */24 + (NSArray *) ys_methodList; 25 26/** 27 return the Protocol array of the current Class 28 29 @ return protocol array 30 */31 + (NSArray *) ys_protocolList; 32 33/** 34 use the dictionary to create the object of the current class 35 36 @ param dictionary 37 38 @ return the object of the current class 39 */40 + (instancetype) ys_objectWithDictionary :( NSDictionary *) dictionary; 41 42/** 43 create an object array of the current class using a dictionary array 44 45 @ param dictArray dictionary array 46 47 @ return object array of the current class 48 */49 + (NSArray *) ys_objectsWithDictionaryArray :( NSArray <NSDictionary *> *) dictArray; 50 51 @ end
2. Next we will implement the method in it and use it to obtain the attributes, member variables, methods, and protocols of classes/objects.
Note: The most important method is in objc/runtime. h. Here we only list some of them and play a role in attracting others.
1 # import "NSObject + YSRuntime. h "2 # import <objc/runtime. h> 3 4 @ implementation NSObject (YSRuntime) 5 6 # pragma mark-attribute array 7 const char * propertiesKey = "ys. propertiesList "; 8 + (NSArray *) ys_propertiesList {9 10 // get the associated object 11 NSArray * result = objc_getAssociatedObject (self, propertiesKey); 12 13 if (result! = Nil) {14 return result; 15} 16 17 unsigned int count = 0; 18 objc_property_t * list = class_copyPropertyList ([self class], & count ); 19 20 NSMutableArray * arrayM = [NSMutableArray array]; 21 22 for (unsigned int I = 0; I <count; I ++) {23 24 objc_property_t pty = list [I]; 25 26 const char * cName = property_getName (pty); 27 NSString * name = [NSString stringwithuf8string: cName]; 28 29 [arrayM add Object: name]; 30} 31 32 free (list); 33 34 // set the correlated Object 35 objc_setAssociatedObject (self, propertiesKey, arrayM, objects); 36 37 return objc_getAssociatedObject (self, propertiesKey); 38} 39 40 # pragma mark-Private method, specifically for custom attributes in the dictionary-to-model, {@ "name": @ "Dog "}, name is the property name, Dog is the custom model class, and property name-attribute type 41 const char * propertiesTypeKey = "ys. propertiesTypeKey "; 42 + (NSArray <NSDictionary *> *) ys_propert IesAndTypeList {43 44 // get the correlated object 45 NSArray * result = objc_getAssociatedObject (self, propertiesTypeKey); 46 47 if (result! = Nil) {48 return result; 49} 50 51 unsigned int count = 0; 52 objc_property_t * list = class_copyPropertyList ([self class], & count ); 53 54 NSMutableArray <NSDictionary *> * arrayM = [NSMutableArray <NSDictionary *> array]; 55 56 for (unsigned int I = 0; I <count; I ++) {57 58 objc_property_t pty = list [I]; 59 60 const char * cType = property_getAttributes (pty); 61 NSString * typeStr = [NSString strin GWithUTF8String: cType]; 62 63 if ([typeStr containsString: @ "\", & "]) {64 nsange typeRange = [typeStr rangeOfString: @" \ ", &"]; 65 NSString * type = [typeStr substringWithRange: NSMakeRange (3, typeRange. location-3)]; 66 67 const char * cName = property_getName (pty); 68 NSString * name = [NSString stringwithuf8string: cName]; 69 70 NSDictionary * dict =@{ name: type}; 71 72 [arrayM addObject: dict]; 73} 74} 75 76 free (list); 77 78 // set the correlated object 79 objc_setAssociatedObject (self, propertiesTypeKey, arrayM, callback); 80 81 return objc_getAssociatedObject (self, propertiesTypeKey ); 82} 83 84 85 # pragma mark-member variable array 86 const char * ivarsKey = "ys. ivarsList "; 87 + (NSArray *) ys_ivarsList {88 89 // get the associated object 90 NSArray * result = objc_getAssociatedObject (self, ivarsKey); 91 92 if (result! = Nil) {93 return result; 94} 95 96 unsigned int count = 0; 97 Ivar * list = class_copyIvarList ([self class], & count ); 98 99 NSMutableArray * arrayM = [NSMutableArray array]; 100 101 for (unsigned int I = 0; I <count; I ++) {102 103 Ivar ivar = list [I]; 104 105 const char * cName = ivar_getName (ivar); 106 NSString * name = [NSString stringwithuf8string: cName]; 107 108 [arrayM addObject: name]; 109} 110 111 free (list); 112 113 // set the correlated object 114 objc_setAssociatedObject (self, ivarsKey, arrayM, callback); 115 116 return objc_getAssociatedObject (self, ivarsKey ); 117} 118 119 # pragma mark-Method array 120 + (NSArray *) ys_methodList {121 122 unsigned int count = 0; 123 Method * list = class_copyMethodList ([self class], & count); 124 125 NSMutableArray * arrayM = [NSMutableArray array]; 126 127 for (unsigned int I = 0; I <count; I ++) {128 129 Method method = list [I]; 130 131 SEL selector = method_getName (method); 132 NSString * name = NSStringFromSelector (selector); 133 134 [arrayM addObject: name]; 135} 136 137 free (list); 138 139 return arrayM. copy; 140} 141 142 # pragma mark-Protocol array 143 + (NSArray *) ys_protocolList {144 145 unsigned int count = 0; 146 _ unsafe_unretained Protocol ** list = class_copyProtocolList ([self class], & count); 147 148 NSMutableArray * arrayM = [NSMutableArray array]; 149 150 for (unsigned int I = 0; I <count; I ++) {151 152 Protocol * protocol = list [I]; 153 154 const char * cName = protocol_getName (protocol); 155 NSString * name = [NSString stringwithuf8string: cName]; 156 157 [arrayM addObject: name]; 158} 159 160 free (list); 161 162 return arrayM. copy; 163} 164 165 # pragma mark-dictionary-> Object of the current class 166 + (instancetype) ys_objectWithDictionary :( NSDictionary *) dictionary {167 168 // attribute array of the current class 169 NSArray * list = [self ys_propertiesList]; 170 171 NSArray <NSDictionary *> * propertyTypeList = [self ys_propertiesAndTypeList]; 172 173 id obj = [self new]; 174 175 for (NSString * key in dictionary) {176 177 if ([list containsObject: key]) {178 179 if ([dictionary [key] isKindOfClass: [NSDictionary class]) {// The attribute value is dictionary 180 181 for (NSDictionary * dict in propertypelist) {182 183 if ([key isEqualToString: [NSString stringWithFormat: @ "% @", dict. allKeys. firstObject]) {184 185 NSString * classTypeStr = dict [key]; 186 Class class = NSClassFromString (classTypeStr); 187 188 id objChild = [class ys_objectWithDictionary: dictionary [key]; 189 190 [obj setValue: objChild forKey: key]; 191} 192 193 194} 195 else if ([dictionary [key] isKindOfClass: [NSArray <NSDictionary *> class]) {// The attribute value is the dictionary array 196 197} 198 else {199 [obj setValue: dictionary [key] forKey: key]; 200} 201} 202 203 return obj; 205} 206 207 # pragma mark-dictionary array-> current Class Object array 208 + (NSArray *) ys_objectsWithDictionaryArray :( NSArray <NSDictionary *> *) dictArray {209 210 if (dictArray. count = 0) {211 return nil; 212} 213 214 // attribute array of the current class 215 NSArray * list = [self ys_propertiesList]; 216 NSArray <NSDictionary *> * propertyTypeList = [self ys_propertiesAndTypeList]; 217 218 NSMutableArray * arrayM = [NSMutableArray array]; 219 for (NSDictionary * dictionary in dictArray) {221 222 id obj = [self new]; 223 224 for (NSString * key in dictionary) {225 226 if ([list containsObject: key]) {227 228 if ([dictionary [key] isKindOfClass: [NSDictionary class]) {// The attribute value is dictionary 229 230 for (NSDictionary * dict in propertypelist) {231 232 if ([key isEqualToString: [NSString stringWithFormat: @ "% @", dict. allKeys. firstObject]) {233 234 NSString * classTypeStr = dict [key]; 235 Class class = NSClassFromString (classTypeStr); 236 237 id objChild = [class ys_objectWithDictionary: dictionary [key]; 238 239 [obj setValue: objChild forKey: key]; 240} 241 242 243} 244 else if ([dictionary [key] isKindOfClass: [NSArray <NSDictionary *> class]) {// The attribute value is the dictionary array 245 246} 247 else {248 [obj setValue: dictionary [key] forKey: key]; 249} 250} 251 252 253 [arrayM addObject: obj]; 254} 255 256 return arrayM. copy; 257} 258 259 @ end
3. Like YYModel, if one property of an object is another custom object, it can also act as a reconnection;
4. Unfortunately, it is the same as YYModel. If an attribute is an array and a generic constraint is added, the generic constraint of this array is not obtained.
I remember, YYModel has this problem. Because generic constraints cannot be obtained, You need to manually specify the element type in the array when the attribute is an array.
I hope you will not be enlightened after seeing this.
5. Finally, I posted a small and very interesting little stuff. The key in it is that I used "ys_ivarsList" to get all the member variables, and then found the member _^ at the first level.
1 // set the random color to the statusBar of the Application. Therefore, the mother no longer needs to worry about the background color of statusBar. 2 id bgStyle = [[UIApplication sharedApplication] valueForKeyPath: @ "statusBar. backgroundView. style "]; 3 [bgStyle setValue: [UIColor redColor] forKey: @" backgroundColor "];
1 // frame = (5 649; 55 13) 2 // modify AMAP and logo, Delete and replace your own custom 3 UIImageView * imgV = [mapView valueForKey: @ "logoImageView"]; // This is the logo4 imgV of AMAP. image = nil; // set the imageView image to nil5 [mapView setValue: imgV forKey: @ "logoImageView"]; // Haha, the logo of this AMAP disappears, mom no longer needs to worry about the logo.