This nine Gongge case:
(1) Import app.plist and a variety of picture material, convenient for follow-up development. The same is true in real-world development.
(2) Import the array in the plist.
-Because in this case app.plist is ultimately an array, the array is a dictionary. So we need an array type to accept this plist file.
--We use the previously mastered data in the getter of the variable to delay loading.
#import "ViewController.h" @interface Viewcontroller () @property (Nonatomic,strong) Nsarray *arr1; @end @implementation viewcontroller-(void) viewdidload { self.arr1; [Super Viewdidload];} -(Nsarray *) arr1{ if (_arr1==nil) { nsstring *path=[[nsbundle mainbundle]pathforresource:@ "App.plist" OfType : nil]; _arr1=[nsarray Arraywithcontentsoffile:path]; NSLog (@ "%@", _arr1); } return _ARR1;} @end
The output is:
{ icon = "icon_00"; Name = "\u5929\u5929\u9177\u8dd1"; }, { icon = "icon_01"; Name = "\u5168\u6c11\u98de\u673a\u5927\u6218"; }, ...
Icon is followed by the name of the icon, and name is followed by names, except that the Chinese is converted to Unicode form, and a Chinese character is a \u****.
(3) Calculation of nine lattice
The key is to use/and the% operation to get the rows and columns of the element, note that the% sign operation can not be cgfloat before and after the conversion is better than the int type.
--cgfloat is actually a collection of float and double. CGFloat can be used in almost all places with float and double. will be resolved automatically based on the current system, if it is a 32-bit system, then float, if it is a 64-bit system, resolves to double.
-(void) Viewdidload { //defines the total number of columns, each nine Gongge the width of the high int totalcolumns=3; CGFloat appw=90; CGFloat apph=100; Define horizontal and Vertical spacing cgfloat marginx= (SELF.VIEW.FRAME.SIZE.WIDTH-TOTALCOLUMNS*APPW)/(totalcolumns+1); CGFloat marginy=20; Initializes and loads a single uiview for (int index=0; index<self.arr1.count; index++) based on the number of data in the arr1. { //Calculate the app in a few rows and columns int row=index/totalcolumns; int col=index%totalcolumns; Create UIView UIView *appview=[[uiview alloc]init]; Based on some calculations, determine the location of the different UIView Appview.frame=cgrectmake (marginx+col* (MARGINX+APPW), 30+row* (MARGINY+APPH), APPW, APPH); Appview.backgroundcolor=[uicolor Redcolor]; [Self.view Addsubview:appview]; } [Super Viewdidload]; Do any additional setup after loading the view, typically from a nib.}
(4) Add a Uiimageview, Uilabel and UIButton to each appview. Added directly to the for loop, which creates the UIView *appview and creates the contents of it.
--among them, Uiimageview pictures used to get the name of the picture, this can be stored in the plist inside, we _arr1 the corresponding dictionary out to use.
The point is that the font size of the UIButton cannot be set directly, but instead is set using the UIButton Titlelabel in the child view. (Because UIButton inside actually encapsulates two sub-view controls, one is the Uilabel *titlelabel of the loaded text, the Uiimageview *imageview of a picture)
for (int index=0; index<self.arr1.count; index++) {//Calculate this app in a few rows of several columns of int row=index/totalcolumns; int col=index%totalcolumns; Create UIView UIView *appview=[[uiview Alloc]init]; Based on some calculations, determine the location of the different UIView Appview.frame=cgrectmake (marginx+col* (MARGINX+APPW), 30+row* (MARGINY+APPH), APPW, APPH);// Appview.backgroundcolor=[uicolor Redcolor]; [Self.view Addsubview:appview]; Get plist each dictionary data nsdictionary *appdic=_arr1[index] According to the index; Add child controls to Appview icon//According to the dictionary to get inside the icon name Uiimageview *appicon=[[uiimageview Alloc]init]; CGFloat iconw=65; CGFloat iconh=65; CGFloat iconx= (APPW-ICONW)/2; CGFloat icony=0; Appicon.frame=cgrectmake (IconX, Icony, Iconw, Iconh); Appicon.image=[uiimage imagenamed:appdic[@ "icon"]; [Appview Addsubview:appicon]; Add child controls to Appview label UILabel *applabel=[[uilabel Alloc]init]; CGFloat LABELW=APPW; CGFloat labelh=20; CGFloat labelx= (APPW-LABELW)/2; CGFloat Labely=icony+iconh; Applabel.frame=cgrectmake (LabelX, labely, Labelw, LABELH); applabel.text=appdic[@ "Name"]; Applabel.textalignment=nstextalignmentcenter; Applabel.font=[uifont systemfontofsize:14]; [Appview Addsubview:applabel]; Add child controls to Appview button UIButton *appbtn=[[uibutton alloc]init]; CGFloat btnw=65; CGFloat btnh=26; CGFloat btnx= (APPW-BTNW)/2; CGFloat Btny=labely+labelh; Appbtn.frame=cgrectmake (Btnx, Btny, BTNW, BTNH); [appbtn settitle:@ "Download" forstate:uicontrolstatenormal]; Appbtn.titlelabel.font=[uifont systemfontofsize:14]; [Appbtn setbackgroundimage:[uiimage imagenamed:@ "Buttongreen"] forstate:uicontrolstatenormal]; [Appbtn setbackgroundimage:[uiimage imagenamed:@ "buttongreen_highlighted"] forstate:uicontrolstatenormal]; [Appview ADDSUBVIEW:APPBTN]; }
(5) most important : dictionary to model
The disadvantage of using a dictionary: you need to use the key value to adjust and set the data, sometimes error, although can be improved with macro variables, but the more fatal to write the wrong key value, there is no error hint.
Model: Strictly called model data. The core is that we think of the dictionary as an object, a few data in the dictionary, we convert to several properties of the object, we call and set the data directly "object. Properties".
So, we need to create a class that is dedicated to storing data, which is often called model classes.
In this example, create a Jiugongge class, declare 2 variables in. h, and 2 initialization methods (specifications are all 2 methods of initialization, in fact the core is one, the second is implemented by the first).
#import <Foundation/Foundation.h> @interface jiugongge:nsobject@property (nonatomic,copy) NSString *name;@ Property (nonatomic,copy) NSString *icon;-(instancetype) Initwithjiugongge: (Nsdictionary *) dic;+ (instancetype) Jiugonggewith: (Nsdictionary *) dic; @end
Implemented in JIUGONGGE.M (note writing, memory):
#import "JiuGongGe.h" @implementation jiugongge-(Instancetype) Initwithjiugongge: (nsdictionary *) dic{ if (self=[ Super Init]) { self.name=dic[@ "name"]; self.icon=dic[@ "icon"]; } return self;} + (Instancetype) Jiugonggewith: (nsdictionary *) dic{ return [[Jiugongge alloc]initwithjiugongge:dic];} @end
In fact, our small title is "dictionary to model", that is, just convert the dictionary into a model (object), the original dictionary is stored in the array, and then through the array [index] one by one call the dictionary, now the Model (object) is still stored in the array. So we need the Getter method for the array to be improved: (Note: You need to #import "JiuGongGe.h" in VIEWCONTROLLER.M because you want to instantiate the object)
-(Nsarray *) arr1{ if (_arr1==nil) { nsstring *path=[[nsbundle mainbundle]pathforresource:@ "App.plist" OfType : nil]; Nsarray *tmparr=[nsarray Arraywithcontentsoffile:path]; Nsmutablearray *muarr1=[[nsmutablearray Alloc]init]; For (Nsdictionary *dict in Tmparr) { Jiugongge *jiugognge=[jiugongge jiugonggewith:dict]; [MuArr1 Addobject:jiugognge]; } _arr1=muarr1; } return _ARR1;}
In the viewdidload for loop, you can use the object. property to invoke the data:
According to the index to get each object, here Appdic name is not changed, or used to take the dictionary before the variable, see not very accustomed to Jiugongge *appdic=_arr1[index]; Add child controls to Appview icon ... Appicon.image=[uiimage ImageNamed:appDic.icon]; Add child controls to Appview label Applabel.text=appdic.name;
(6) Jiugonggewith: (Nsdictionary *) dic; Improvement of initialization method
-The name of the class used inside can be replaced by self. Because the subclass is prevented from having subclasses, if the subclass calls Jiugonggewith: (Nsdictionary *) dic, the method that calls to the parent class is written with the name of the parent class, and the initialization result is an object of the parent class, not the object of the child class. So with self, who calls on the object whose initialization is initialized.
(7) Description of ID type and instancetype
--instancetype and ID are all universal pointers.
--ios recommends that we use INSTANCETYPE instead of ID. Although many of the official Init method's return values are also IDs.
The advantage of using an ID is that the ID is a universal pointer, and we don't have to worry about the problem of its return value type mismatch.
The disadvantage of using ID: It is also because it is a universal pointer, we can accept the return value with arbitrary pointers, such as NSString *str1=****,nsarray *arr1=****, this code is written out to not error. But it may not be the type of return value we need.
The advantage of using instancetype is that if our return value is an object, then you accept the return value with the above two arbitrary pointers, it will have a warning warning, we will use the class object Jiugongge *jiugognge=***, will not be warned.
--instancetype can only be used on return value types and cannot be used as an ID on parameters.
(8) Reduce code with xib graphical layout
The difference between Xib and storyboard is that storyboard describes the entire program interface, and Xib is used to describe the local repeating interface.
For example, there are 12 applications in this example, each application view is the same, can be implemented with Xib, and then xib loaded in.
Creation of Xib (with empty):
Layout in Ourxib:
--For Uiimageview and Uilabel, set the tag to 10 and 20 respectively for easy invocation.
--Drag the control to the interface, when changing the size, Uiimageview need to set size to freeform to resize.
Once the ourxib is set up, you can call:
--Except for resources outside the picture, it needs to be called with [NSBundle Mainbundle].
--the method of calling the Xib file is the Loadnibnamed method of the Mainbundle.
for (int index=0; index<self.arr1.count; index++) { //calculate this app in a few rows of several columns of int row=index/totalcolumns; int col=index%totalcolumns; Get each object according to the index Jiugongge *appdic=_arr1[index]; Nsarray *xibarr=[[nsbundle mainbundle]loadnibnamed:@ "Ourxib" Owner:nil Options:nil]; UIView *xibview=[xibarr Lastobject]; Xibview.frame=cgrectmake (marginx+col* (MARGINX+APPW), 30+row* (MARGINY+APPH), APPW, APPH); Uiimageview *imgview2= (Uiimageview *) [Xibview viewwithtag:10]; Imgview2.image=[uiimage ImageNamed:appDic.icon]; UILabel *label2= (UILabel *) [Xibview viewwithtag:20]; Label2.text=appdic.name; Add to Main view [Self.view Addsubview:xibview]; }
(9) What is the relationship between the Xib file and the nib file?
The--xib file is something that our developers saw when they developed it;
-While running on a user's phone, the Xib file is converted to a nib file.
We can view it in the sandbox generated by iOS simulator.
--Unable to find the repository path, directly with NSLog (@ "%@", [NSBundle mainbundle), and print out the path.
Find out that the repository does have a ourxib.nib file, and the Xib file does turn into a nib file.
"iOS Development-48" Nine Gongge layout cases: Automatic layout, dictionary to model use, ID and instancetype differences, xib repetition view usage and nib relationship