IOS Study Notes 38-MJExtension

Source: Internet
Author: User
Tags array example user definition

IOS Study Notes 38-MJExtension
I. MJExtension third-party framework

During iOS development, we often need to convert Dictionary data (that is, JSON data) to Model data, such as Weibo data returned by network requests, if we manually create models and assign values, they are all technical code that is time-consuming and labor-consuming, and may also cause assignment errors, which makes us a headache.

MJExtensionThe framework is designed with a third-party open-source library to solve this problem. This open-source library was written by Dr. Yan Jie, a lecturer from Zhizhi's blog. Now he has made it by himself. I am getting started with iOS, and I am reading the training video from instructor Yan Jie. He spoke very well, I like him very much. He is also my teacher. I still want to learn his work.

Provides the following methods: simple dictionary-> model JSON string-> model complex dictionary-> model (the model contains the Model) complex dictionary-> model (the model is included in the array attribute of the model) complex dictionary-> model (the model attribute name and the dictionary key are different) dictionary array-> model array model-> dictionary model array-> dictionary array dictionary-> CoreData model archive and archive NSCoding filter dictionary values

MJExtensionThe framework is written using the runtime mechanism of Obj-C. Now the iOS development language is evolving towards the Swift language. I am not sure whether the Swift language also has this feature, it is unknown whether the framework will continue to develop in the Swift language in the future. However, this framework is lightweight and suitable for beginners to look at its source code, it is of great help to understand the runtime mechanism of Obj-C.

II. A brief understanding of the Runtime Mechanism

RuntimeFor short, runtime refers to some mechanisms of the system during runtime, the most important of which isMessage Mechanism.

OC Function calls are similarMessage sendingIs a dynamic call process. During compilation, you cannot decide which function to call. It turns out that in the compilation phase, OC can call any function. Even if this function is not implemented, no error will be reported if it has been affirmed. C language reports an error during compilation. The corresponding function can be called only when the function is running.

For example, the following code is converted during compilation:
/* OC method call */[obj makeTest];/* during compilation, Runtime will convert the above Code into the following message and send */objc_msgSend (obj, @ selector (makeText ));
The top-level base class NSObject of iOS contains an isa pointer pointing to the objc_class struct:
@ Interface NSObject {Class isa;}; typedef struct objc_class * Class; struct objc_class {Class isa; // point to metaclass, that is, static Class super_class; // point to the parent class const char * name; // class name long version; // class version information. The default value is 0/*. For example, CLS_CLASS (0x1L) indicates that the class is a common class; CLS_META (0x2L) indicates that the class is metaclass */long info; long instance_size; // The instance variable size of the class (including the instance variables inherited from the parent class ); struct objc_ivar_list * ivars; // address used to store each member variable/* is related to some flag bits of info. If it is a common class, the object method is stored, and if it is metaclass, the class method is stored; */struct objc_method_list ** methodLists; struct objc_cache * cache; // pointer to the recently used method to improve efficiency; struct objc_protocol_list * protocols; // store the protocols that this class complies };

In objc_msgSendFunction call process: first, find the Class corresponding to obj through the isa pointer of obj. Go first in Class cacheUsing SEL to find the corresponding function methodIf cacheNot found. methodListsIf methodListsIf not found, enter superClassPerform recursive search according to the previous steps. method methodAdd cacheTo facilitate the next search and methodThe function pointer in to jump to the corresponding function for execution. If you find NSObjectIf no message is found, the dynamic message processing process is displayed. Message dynamic processing process:
/* 1. in this method, we can use the runtime feature to dynamically add methods to process */+ (BOOL) resolveInstanceMethod :( SEL) sel;/* 2. second, check whether the proxy can process the time. If the proxy object can be processed, it is transferred to the proxy object */-(id) forwardingTargetForSelector :( SEL) aSelector;/* 3. one of message forwarding. This method returns the method signature. If nil is returned, the forwarding process ends and an exception */-(NSMethodSignature *) methodSignatureForSelector :( SEL) aSelector;/* 4. message forwarding 2. In this method, we can redirect the calling Method */-(void) forwardInvocation :( NSInvocation *) anInvocation;

So we can dynamically add methods or attributes to the class using the Runtime mechanism:
/* Dynamically add attributes to a class */class_addIvar (kclass, "expression", size, alignment ,"*"); /* dynamically add methods to a class */class_addMethod (kclass, @ selector (setExpressionFormula :), (IMP) setExpressionFormula, "v @: @"); class_addMethod (kclass, @ selector (getExpressionFormula), (IMP) getExpressionFormula, ":"); static void setExpressionFormula (id self, SEL cmd, id value) {NSLog (@ "call setExpressionFormula");} static id getExpressionFormula (id self, SEL cmd) {NSLog (@ "call getExpressionFormula"); return nil ;}
vVoid, @Id type, :SEL type "v@:@": Indicates that the return value is void, and a method of id type, SEL type, and id type is accepted. "@@:": Indicates that the return value is of the id type, and the method that accepts an id type and a SEL type parameter

Here we will not elaborate on the specific usage details of Runtime, but simply understand that Runtime can dynamically add attributes and methods to the class.

Iii. Use MJExtension

MJExtensionMost of the methods are integrated into the classification. You do not need to use new classes, but only need to include header files.MJExtension.hYou can.MJExtensionThe instructions on github have been clearly written.

1. simple dictionary-> model class User definition:
Typedef enum {SexMale, SexFemale} Sex; @ interface User: NSObject @ property (copy, nonatomic) NSString * name;/* name */@ property (copy, nonatomic) NSString * icon;/* Avatar */@ property (assign, nonatomic) unsigned int age;/* age */@ property (copy, nonatomic) NSString * height; /* height */@ property (strong, nonatomic) NSNumber * money;/* asset */@ property (assign, nonatomic) Sex; /* Gender */@ property (assign, nonatomic, getter = isGay) BOOL gay;/* Whether it is gay */@ end
Instance used:
NSDictionary * dict =@ {@ "name": @ "Jack", @ "icon": @ "lufy.png", @ "age": @ 20, @ "height ": @ "1.55", @ "money": @ 100.9, @ "sex": @ (SexFemale),/* NSNumber packaging is required for enumeration */@ "gay ": @ "NO"}; // dictionary to model, using mj_objectWithKeyValues: Method User * user = [User mj_objectWithKeyValues: dict];
2. JSON string-> model use instance:
// Define a JSON string NSString * jsonString = @ "{\" name \ ": \" Jack \ ", \" icon \ ": \" lufy.png \", \ "age \": 20} "; // convert the JSON string to the model User * user = [User mj_objectWithKeyValues: jsonString];
3. Complex dictionary-> model (the model contains the model) model class Status definition:
@ InterfaceStatus: NSObject @ property (copy, nonatomic) NSString * text; @ property (strong, nonatomic) User * user;/* Other model types */@ property (strong, nonatomic) status * retweetedStatus;/* Self-model type */@ end
Instance used:
NSDictionary * dict =={ @ "text": @ "Agree! Nice weather! ", @" User ": @ {@" name ": @" Jack ", @" icon ": @" lufy.png "}, @" retweetedStatus ": @ {@ "text": @ "Nice weather! ", @" User ": @ {@" name ": @" Rose ", @" icon ": @" nami.png "}}; // dictionary conversion model, the model contains the model Status * status = [Status mj_objectWithKeyValues: dict]; NSString * text = status. text; NSString * name = status. user. name; NSString * icon = status. user. icon; NSLog (@ "text = % @, name = % @, icon = % @", text, name, icon); // text = Agree! Nice weather !, Name = Jack, iconw.lufy.png NSString * text2 = status. retweetedStatus. text; NSString * name2 = status. retweetedStatus. user. name; NSString * icon2 = status. retweetedStatus. user. icon; NSLog (@ "text2 =%@, name2 =%@, icon2 =%@", text2, name2, icon2); // text2 = Nice weather !, Name2 = Rose, icon2?nami.png
4. Complex dictionary-> model (the model is included in the array attribute of the model) model class Ad and StatusResult definition:
@ InterfaceAd: NSObject @ property (copy, nonatomic) NSString * image; @ property (copy, nonatomic) NSString * url; @ end @ interfaceStatusResult: store model Status data in the NSObject/** array */@ property (strong, nonatomic) NSMutableArray * statuses; /** store model Ad data in the array */@ property (strong, nonatomic) NSArray * ads; @ property (strong, nonatomic) NSNumber * totalNumber; @ end # import "MJExtension. h "/* indicates the model data type stored in the array */@ implementation StatusResult/* to store model data, description: The model data type stored in the array */+ (NSDictionary *) mj _ objectClassInArray {return @ {@ "statuses": @ "Status", @ "ads ": @ "Ad" };}@ end
Instance used:
NSDictionary * dict =@{@ "statuses": @ [{@ "text": @ "Nice weather! ", @" User ": @ {@" name ": @" Rose ", @" icon ": @" nami.png "}}, @ {@" text ": @ "Go camping tomorrow! ", @" User ": @ {@" name ": @" Jack ", @" icon ": @" lufy.png "}], @" ads ": @ [@ {@ "image": @ "ad01.png", @ "url": @ "http://www.ad01.com"}, @ {@ "image": @ "ad02.png ", @ "url": @ "http://www.ad02.com"}], @ "totalNumber": @ "2014"}; // dictionary conversion model, the array attribute of the supported model contains the model StatusResult * result = [StatusResult mj_objectWithKeyValues: dict]; // print the blogger information for (Status * status in result. statuses) {NSString * text = status. text; NSS Tring * name = status. user. name; NSString * icon = status. user. icon; NSLog (@ "text =%@, name =%@, icon =%@", text, name, icon) ;}// text = Nice weather !, Name = Rose, iconw.nami.png // text = Go camping tomorrow !, Name = Jack, iconw.lufy.png // print the Ad for (ad * Ad in result. ads) {NSLog (@ "image =%@, url =%@", ad. image, ad. url);} // image%ad01.png, url = http://www.ad01.com // image%ad02.png, url = http://www.ad02.com
5. Complicated dictionary-> model (the model attribute name and the dictionary key are different) model class Bag and Student definition:
@ Interface Bag: NSObject @ property (copy, nonatomic) NSString * name; @ property (assign, nonatomic) double price; @ end @ interface Student: NSObject @ property (copy, nonatomic) NSString * ID; @ property (copy, nonatomic) NSString * desc; @ property (copy, nonatomic) NSString * nowName; @ property (copy, nonatomic) NSString * oldName; @ property (copy, nonatomic) NSString * nameChangedTime; @ property (strong, nonatomic) Bag * bag; @ end # import "MJExtension. h "@ implementation/* set the ing relationship between model attribute names and dictionary keys */+ (NSDictionary *) The dictionary returned by mj_replacedKeyFromPropertyName {/*. The key is the model attribute name, the value is the multilevel key */return @ {@ "ID": @ "id", @ "desc": @ "desciption", @ "oldName ": @ "name. oldName ", @" nowName ": @" name. newName ", @" nameChangedTime ": @" name.info [1]. nameChangedTime ", @" bag ": @" other. bag "};}@ end
Instance used:
NSDictionary * dict =@ {@ "id": @ "20", @ "desciption": @ "kids", @ "name": @ {@ "newName ": @ "lufy", @ "oldName": @ "kitty", @ "info": @ [@ "test-data", @ {@ "nameChangedTime ": @ "2013-08"}]}, @ "other": @ {@ "bag": @ {@ "name": @ "a red bag ", @ "price": @ 100.7 }}; // dictionary-to-model conversion, supports multi-level stuing Student * stu = [Student mj_objectWithKeyValues: dict]; // print NSLog (@ "ID = % @, desc = % @, oldName = % @, nowName = % @, nameChangedTime = % @", stu. ID, stu. desc, stu. oldName, stu. nowName, stu. nameChangedTime); // ID = 20, desc = kids, oldName = kitty, nowName = lufy, nameChangedTime = 2013-08NSLog (@ "bagName = % @, bagPrice = % f", stu. bag. name, stu. bag. price); // bagName = a red bag, bagPrice = 100.700000.
6. dictionary array-> model array example:
NSArray * dictArray = @ [@ {@ "name": @ "Jack", @ "icon": @ "lufy.png"}, @ {@ "name ": @ "Rose", @ "icon": @ "nami.png"}]; // convert a dictionary array to a model Array Using mj_objectArrayWithKeyValuesArray: Method NSArray * userArray = [User mj_objectArrayWithKeyValuesArray: dictArray]; // print for (User * user in userArray) {NSLog (@ "name = % @, icon = % @", user. name, user. icon);} // name = Jack, iconw.lufy.png // name = Rose, iconw.nami.png
7. Model-> dictionary instance:
// Create a model object User * user = [[User alloc] init]; user. name = @ "Jack"; user. icon = @ "lufy.png"; Status * status = [[Status alloc] init]; status. user = user; status. text = @ "Nice mood! "; // Model to dictionary, using the mj_keyValues attribute NSDictionary * statusDict = status. mj_keyValues; NSLog (@ "% @", statusDict);/* {text = "Nice mood! "; User = {icon =" lufy.png "; name = Jack ;};}*/
8. Model array-> dictionary array example:
// Create a model array User * user1 = [[User alloc] init]; user1.name = @ "Jack"; user1.icon = @ "lufy.png "; user * user2 = [[User alloc] init]; user2.name = @ "Rose"; user2.icon = @ "nami.png"; NSArray * userArray = @ [user1, user2]; // model array to dictionary array, using mj_keyValuesArrayWithObjectArray: Method NSArray * dictArray = [User mj_keyValuesArrayWithObjectArray: userArray]; NSLog (@ "% @", dictArray ); /* ({icon = "lufy.png"; name = Jack ;}, {icon = "nami.png"; name = Rose ;})*/
9. dictionary-> CoreData model instance:
NSDictionary * dict =@ {@ "name": @ "Jack", @ "icon": @ "lufy.png", @ "age": @ 20, @ "height ": @ 1.55, @ "money": @ "100.9", @ "sex": @ (SexFemale), @ "gay": @ "true "}; // convert the dictionary to CoreData model NSManagedObjectContext * context = nil; User * user = [User mj_objectWithKeyValues: dict context: context]; [context save: nil];
10. How to add an archive and archive NSCoding model class Bag:
@ Interface Bag: NSObject
  
   
@ Property (copy, nonatomic) NSString * name; @ property (assign, nonatomic) double price; @ end # import "MJExtension. h "@ implementation Bag // added the following macro definition MJExtensionCodingImplementation/* to implement the following method, indicating which attributes do not need archive and archive */+ (NSArray *) mj_ignoredCodingPropertyNames {return @ [@ "name"] ;}@ end
  
Instance used:
// Create model Bag * bag = [[Bag alloc] init]; bag. name = @ "Red bag"; bag. price = 200.8; // obtain the archive path NSString * file = [NSHomeDirectory () stringByAppendingPathComponent: @ "Desktop/bag. data "]; // archive [NSKeyedArchiver archiveRootObject: bag toFile: file]; // archive Bag * decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile: file]; NSLog (@ "name = % @, price = % f", decodedBag. name, decodedBag. price); // name = (null), price = 200.800000
11. Implement the value model class Book of the filter dictionary:
@ Interface Book: NSObject @ property (copy, nonatomic) NSString * name; @ property (strong, nonatomic) NSDate * publishedTime; @ end # import "MJExtension. h "@ implementation Book/* filter and further convert dictionary values during conversion */-(id) mj_newValueFromOldValue :( id) oldValue property :( MJProperty *) property {if ([property. name isEqualToString: @ "publisher"]) {if (oldValue = nil) {return @ "" ;}} else if (property. type. typeClass = [NSDate class]) {NSDateFormatter * fmt = [[NSDateFormatter alloc] init]; fmt. dateFormat = @ "yyyy-MM-dd"; return [fmt dateFromString: oldValue];} return oldValue;} @ end
Instance used:
NSDictionary * dict =@ {@ "name": @ "5-minute breakthrough in iOS development", @ "publishedTime": @ "2011-09-10"}; // dictionary conversion model, when the name is nil, convert NSString to NSDateBook * book = [Book mj_objectWithKeyValues: dict]; // print NSLog (@ "name = % @, publishedTime = % @", book. name, book. publishedTime );

MJExtensionFor the github address, click here: CoderMJLee/MJExtension

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.