iOS Development UI Chapter-Dictionary to model
A "problem code" to complete the function
1. Data loaded from the plist
2. Implementing the Code
1//2//LFVIEWCONTROLLER.M 3//03-Application Management 4//5//Created by Apple on 14-5-22. 6//Copyright (c) 2014 Heima. All rights reserved. 7//8 9 #import "LFViewController.h" @interface Lfviewcontroller () @property (nonatomic, strong) Nsarray *applis t;13 @end14 @implementation LFViewController16-(Nsarray *) appList18 {20 21//1. From M Ainbundle load NSBundle *bundle = [NSBundle mainbundle];23 nsstring *path = [bundle pathforresource:@] App.p List "oftype:nil];24 _applist = [Nsarray arraywithcontentsoffile:path];25 NSLog (@"%@ ", _applist )}28 return _applist;29}30-(void) viewDidLoad32 {[Super VIEWDIDLOAD];34 35//Total 3 Columns 36 int totalcol = 3;37 cgfloat vieww = 80;38 cgfloat viewh = 90;39 + cgfloat Marginx = (self.view.bounds.siz E.width-totalcol * vieww)/(Totalcol + 1); CGFloat marginy = 10;42 cgfloat starty = 20;43 for (int i = 0; i < Self.appList.count; i++) {int row = i/totalcol;47 int col = i% totalcol;48 cgfloat x = Marginx + ( VIEWW + marginx) * col;50 cgfloat y = starty + marginy + (VIEWH + marginy) * row;51 UIView *app View = [[UIView alloc] Initwithframe:cgrectmake (x, Y, Vieww, VIEWH)];53 [Self.view addsubview:appview];55 56//Create Appview internal details//0> read the dictionary in the array nsdictionary *dict = self.applist[i];59 //1> UIImageView61 Uiimageview *imageview = [[Uiimageview alloc] Initwithframe:cgrectmake (0, 0, V IEWW,];62 imageview.image = [UIImage imagenamed:dict[@ "icon"]];63 Imageview.contentmode = Uiviewconten tmodescaleaspectfit;64 [Appview addsubview:imageview];65//2> UILabel67 UILabel *la Bel = [[UILabel alloc] Initwithframe:cgrectmake (0, ImageView.bounds.size.height, VIEWW, 20)];68//Set Text 69 Label.text = dict[@ "Name"];70 Label.font = [Uifont systemfontofsize:12.0];71 label.textalignment = NST extalignmentcenter;72 [Appview addsubview:label];74//3> UIButton76//U Ibuttontypecustom and [[UIButton alloc] init] are equivalent to the UIButton *button = [UIButton buttonwithtype:uibuttontypecustom];78 Button.frame = CGRectMake (n, A, viewW-30,); [Button settitle:@ "Download" Forstate:uicontrol STATENORMAL];81//* * * cannot be directly set with the following code title82//Button.titleLabel.text = @ "Download";//@property Readon Ly indicates that the object's pointer address is not allowed to be modified, but the object's properties can be modified by button.titlelabel.font= [Uifont systemfontofsize:14.0];85 [Butto n setbackgroundimage:[uiimage imagenamed:@ "Buttongreen"] forstate:uicontrolstatenormal];87 [button setBackgroundIm Age:[uiimage imagenamed:@ "buttongreen_highlighted"] forstate:uicontrolstatehighlighted];88 [AppView add SUBVIEW:BUTTON];90}}92 @end
3. Achieving results
4. Code issues
In the above code 62nd, 69 lines, we are directly through the dictionary key name to obtain the data in the plist, in the Viewcontroller need to work directly with the data, if the need for multiple use may be careless to write the key name wrong, and the program does not error. For this reason, consider converting the dictionary data into a model, encapsulating the data into a model, and letting Viewcontroller no longer interact directly with the data, but interacting with the model.
In general, both the set data and the Fetch data use "String type Key", when writing these keys, the editor does not have a smart hint, need to hand knock. Such as:
dict[@ "name"] = @ "Jack";
NSString *name = dict[@ "name"];
Hand knocking string Key,key easy to write wrong
If the key is incorrectly written, the compiler will not have any warnings or errors, resulting in incorrect data or incorrect data.
Second, dictionary to model
1. Dictionary to model Introduction
:
The benefits of dictionary-to-model:
(1) Reduce the coupling degree of the code
(2) The Code of all dictionary-to-model parts is centrally handled in one place, reducing the chance of code errors
(3) using the model's attribute operation directly in the program to improve the coding efficiency
(4) The caller does not care about any processing details inside the model
Note Points for dictionary to model:
The model should provide a construction method that can pass in the dictionary parameters
-(Instancetype) Initwithdict: (Nsdictionary *) dict;
+ (Instancetype) xxxwithdict: (Nsdictionary *) dict;
Tip: You can further reduce the coupling of your code by using the read-only attribute reasonably in the model.
2. code example (i)
Create a new class to use as the data model
VIEWCONTROLLER.M File Code (dictionary to model)
1 #import "LFViewController.h" 2 #import "LFAppInfo.h" 3 4 @interface Lfviewcontroller () 5 @property (nonatomic, S Trong) Nsarray *applist; 6 @end 7 8 @implementation Lfviewcontroller 9 10//dictionary to model one-(Nsarray *) applist {if (!_applist) {14 1. Load from mainbundle nsbundle *bundle = [NSBundle mainbundle]; NSString *path = [Bundle pathforresource:@ "App.plist" oftype:nil]; +//_applist = [Nsarray Arraywithcontentsoffile:path]; Nsarray *array = [Nsarray Arraywithcontentsoffile:path]; 20//converting an array into a model means that the Lfappinfo object is stored in Self.applist 21//1. Iterates through the array, converting the dictionary in the array to the AppInfo object in turn, adding to a temporary array of 22//2. self.applist = Temporary array Nsmutablearray *arraym = [Nsmutablearray array]; (nsdictionary *dict in array) {26//dictionary to instantiate the object's factory method [Arraym Addobject:[lfappinfo Appinfowithdict:dict]]; _applist = Arraym; + + RETUrn _applist; -(void) viewdidload [[Super Viewdidload]; 38 39//Total 3 columns, int totalcol = 3; Gfloat vieww = 80; CGFloat VIEWH = 90; CGFloat Marginx = (Self.view.bounds.size.width-totalcol * vieww)/(Totalcol + 1); CGFloat marginy = 10; CGFloat starty = 20; (int i = 0; i < Self.appList.count; i++) {$ int row = I/totalcol; = i% Totalcol; CGFloat x = Marginx + (vieww + marginx) * COL; CGFloat y = starty + marginy + (VIEWH + marginy) * ROW; UIView *appview = [[UIView alloc] Initwithframe:cgrectmake (x, Y, Vieww, VIEWH)]; [Self.view Addsubview:appview]; 59 60//Create Appview inside details--0> read appinfo in array//nsdictionary *dict = self.applist[ I]; Lfappinfo *appinfo = Self.applist[i]; +//1> Uiimageview 66 Uiimageview *imageview = [[Uiimageview alloc] Initwithframe:cgrectmake (0, 0, VIEWW, 50)]; Imageview.image = Appinfo.image; Imageview.contentmode = Uiviewcontentmodescaleaspectfit; [Appview Addsubview:imageview]; UILabel//2> UILabel *label = [[UILabel alloc] Initwithframe:cgrectmake (0, ImageView . Bounds.size.height, VIEWW, 20)]; 74//Set text Label.text = Appinfo.name; Label.font = [Uifont systemfontofsize:12.0]; Label.textalignment = Nstextalignmentcenter; [Appview Addsubview:label]; 3> UIButton//Uibuttontypecustom and [[UIButton alloc] init] are equivalent to the UIButton *button = [UIButton buttonwithtype:uibuttontypecustom]; Button.frame = CGRectMake (viewW-30, 20); [Button settitle:@ "Download" forstate:uicontrolstatenormal]; button.titlelabel.font= [Uifont SySTEMFONTOFSIZE:14.0]; [Button setbackgroundimage:[uiimage imagenamed:@ "Buttongreen"] forstate:uicontrolstatenormal]; [Button setbackgroundimage:[uiimage imagenamed:@ "buttongreen_highlighted"] forstate:uicontrolstatehighlighted]; [Appview Addsubview:button]; Button.tag = i; 94 [Button Addtarget:self action: @selector (Downloadclick:) forcontrolevents:uicontroleventtouchupinsid E]; 98-(void) Downloadclick: (UIButton *) button100 {101 NSLog (@ "%d", Button.tag); 102//Instantiate a Uilabel Displayed on the view, prompting the user to download complete 103 UILabel *label = [[UILabel alloc] Initwithframe:cgrectmake (up, up, down, max)];104 Label.textali gnment = nstextalignmentcenter;105 Label.backgroundcolor = [uicolor lightgraycolor];106 107 LFAppInfo *appInfo = self.applist[button.tag];108 Label.text = [nsstring stringwithformat:@ "Download%@ complete", appinfo.name];109 Label.font = [Uifont systemfontofsize:13.0];110 Label. Alpha = 1.0;111 [Self.view addsubview:label];112 113//Animation effect 114//After the animation effect is complete, remove the label from the View 115//end-to-end animation, Can only do animation, to deal with the completion of the operation is not easy to do//[UIView Beginanimations:nil context:nil];117//[UIView setanimationduration:1.0];118// Label.alpha = 1.0;119//[UIView commitanimations];120 121//Block animation is simpler than the primary and end animation, and can control the action after the animation 122//In iOS, basic use End-to-end animation 123 [UIView animatewithduration:2.0 animations:^{124 label.alpha = 0.0;125} completion:^ (BOOL finish ED) {126//delete label127 [Label removefromsuperview];128}];129}130 131 @end
Model. h File Code
1 #import <Foundation/Foundation.h> 2 3 @interface lfappinfo:nsobject 4 5//Application name 6 @property (nonatomic , copy) NSString *name; 7//Application icon name 8 @property (nonatomic, copy) NSString *icon; 9 10///Image 11//The Getter&setter method is generated when the attribute is defined, and an underlined member variable 12//If it is a ReadOnly property, only the Getter method is generated, and no member variable is @property ( Nonatomic, Strong, ReadOnly) UIImage *image;14//Instancetype will let the compiler check the exact type of the instantiated object.//Instancetype can only be used for return types and cannot be used as parameters 17 (instancetype) Initwithdict: (nsdictionary *) dict;19/** Factory method */20 + (Instancetype) appinfowithdict: (NSDictionary *) Dict;21 @end
Model. m File Data processing code
1 #import "LFAppInfo.h" 2 3 @interface lfappinfo () 4 {5 UIImage *_imageabc; 6} 7 @end 8 9 @implementation LF AppInfo10-(Instancetype) Initwithdict: (Nsdictionary *) dict12 {"Self " = [Super Init];14 if (self) { Self.name = dict[@ "name"];16 Self.icon = dict[@ "icon"];17 }18 return self;19}20 + (instancetype) Appinfowithdict: (nsdictionary *) dict22 {[self alloc] initwithdict:dict];24}25-(UIImage *) Image27 {28 if (!_imageabc) { _imageabc = [UIImage imagenamed:self.icon];30 }31 return _imageabc;32}33 34 @ End
3. code example (ii)
Data information: plist file
Dictionary turn model (Preliminary)
Model. h file
1 #import <Foundation/Foundation.h> 2 3 @interface lfquestion:nsobject 4 5 @property (nonatomic, copy) NSS Tring *answer; 6 @property (nonatomic, copy) NSString *title; 7 @property (nonatomic, copy) NSString *icon; 8 @property (nonatomic, strong) Nsarray *options; 9 @property (nonatomic, strong) UIImage *image;11 12/** Instantiate a member method of an object in a dictionary */13-(instancetype) Initwithdict: (nsdictionary *) Dict;14/** class method for instantiating an object in a dictionary, also known as the factory method */15 + (Instancetype) questionwithdict: (nsdictionary *) dict;16 @end
Model. m file
1 #import "LFQuestion.h" 2 3 @implementation lfquestion 4 5 + (Instancetype) questionwithdict: (Nsdictionary *) Dict 6 {7 return [[Self alloc] initwithdict:dict]; 8} 9-(Instancetype) Initwithdict: (Nsdictionary *) dict11 {12
self = [Super init];13 if (self) { self.answer = dict[@ "Answer"];15 Self.icon = dict[@ "icon"];16 Self.title = dict[@ "title"];17 self.options = dict[@ "Options"];18 [self setvaluesforkeyswithdictionary: Dict];20 }21 return self;22}
Data processing in the VIEWCONTROLLER.M file
1-(Nsarray *) Questions 2 {3 if (!_questions) {4 5 nsarray *array = [Nsarray arraywithcontentsoffile:[[nsbu Ndle Mainbundle] pathforresource:@ "Questions.plist" Oftype:nil]]; 6 7 nsmutablearray *arraym = [Nsmutablearray array]; 8 9 for (nsdictionary *dict in array) {ten [ Arraym addobject:[lfquestion questionwithdict:dict]];11 }12 _questions=arraym;13 }14 Return _ QUESTIONS;15}
Dictionary to Model (optimization)
The above code can be further optimized, reading from the plist file can be handed to the model to deal with, optimized after the code is as follows:
Model. h file
1 #import <Foundation/Foundation.h> 2 3 @interface lfquestion:nsobject 4 5 @property (nonatomic, copy) NSS Tring *answer; 6 @property (nonatomic, copy) NSString *title; 7 @property (nonatomic, copy) NSString *icon; 8 @property (nonatomic, strong) Nsarray *options; 9 @property (nonatomic, strong) UIImage *image;11 12/** Instantiate a member method of an object in a dictionary */13-(instancetype) Initwithdict: (nsdictionary *) Dict;14/** class method for instantiating objects using a dictionary, also known as factory method */15 + (Instancetype) questionwithdict: (Nsdictionary *) dict;16 17/** loading an array of objects from Plist */18 + (Nsarray *) questions;19 @end
Model. m file
1 #import "LFQuestion.h" 2 3 @implementation lfquestion 4 5 + (Instancetype) questionwithdict: (Nsdictionary *) Dict 6 {7 return [[Self alloc] initwithdict:dict]; 8} 9-(Instancetype) Initwithdict: (Nsdictionary *) dict11 {12
self = [Super init];13 if (self) { self.answer = dict[@ "Answer"];15 Self.icon = dict[@ "icon"];16 Self.title = dict[@ "title"];17 self.options = dict[@ "Options"];18 [self Setvaluesforkeyswithdictionary:dict];20 }21 return self;22}23 + (Nsarray *) questions26 { Nsarray *array = [Nsarray arraywithcontentsoffile:[[nsbundle mainbundle] pathforresource:@ "Questions.plist" OfType: nil]];28 Nsmutablearray *arraym = [Nsmutablearray array];30 to (nsdictionary *dict in array ) { [Arraym addobject:[lfquestion questionwithdict:dict]];33 }34 return arraym;36}37 @end
Part of the data processing code in the VIEWCONTROLLER.M file
1-(Nsarray *) questions2 {3 if (!_questions) {4 _questions = [lfquestion questions];5 }6 Return _ QUESTIONS;7}
Supplemental content: Use of (KVC)
(1) In the data processing part of the model, it can be processed with the key value code.
1-(Instancetype) Initwithdict: (Nsdictionary *) Dict 2 {3 Self = [Super init], 4 if (self) {5// Self.answer = dict[@ "Answer"]; 6// Self.icon = dict[@ "icon"]; 7// Self.title = dict[@ "title"]; 8// self.options = dict[@ "Options"]; 9 Ten //KVC (key value coding) key value code one //cocoa of the big strokes, allowing indirect modification of the object's property values/ //The first parameter is the value of the dictionary. //The second parameter is the property of the class [Self setvalue:dict[@ ' answer '] forkeypath:@ "answer"];15 [Self setvalue:dict[@ "icon"] forkeypath:@ "icon"];16 [self setvalue:dict[@ "title"] forkeypath:@ "title"];17 [Self setvalue:dict[@ "options"] forkeypath:@ "Options"];18 }19 return self;20}
(2) Use of Setvaluesforkeys
The above data operation details can be done directly through the Setvaluesforkeys method.
1-(Instancetype) Initwithdict: (Nsdictionary *) dict2 {3 Self = [Super Init];4 if (self) {5 /// Using Setvaluesforkeys requires that the properties of a class must exist in the dictionary, and can be more than the key values in the dictionary, but not less. 6 [self setvaluesforkeyswithdictionary:dict];7 }8 return self;9}
Iii. Additional Information
1.readonly Properties
(1) readonly in @property indicates that the object's pointer address is not allowed, but the properties of the object can be modified.
(2) When a property is typically defined using the @property keyword, the Getter&setter method is generated and an underlined member variable is generated.
(3) In the case of the ReadOnly property, only getter methods are generated and no underlined member variables are generated.
2.instancetype type
(1) Instancetype will let the compiler check the exact type of the instantiated object
(2) Instancetype can only be used for return types and cannot be used as parameters
Comparison of 3.instancetype & IDs
(1) Instancetype on a type representation, as with an ID, can represent any object type
(2) Instancetype can only be used on return value types and cannot be used as an ID on parameter types
(3) One more benefit of instancetype than ID: The compiler detects the true type of instancetype
iOS Development UI Chapter-Dictionary to model