"iOS Dev-44" Talk about iOS code refactoring with cases: merging, formatting output, macro variables, storing data using an array dictionary, and using Plist's ultimate knowledge

Source: Internet
Author: User

First of all, our case today is the following 5 pages from the previous next to switch:



(1) The first step, basically is a very silly very direct way to create, the main points used here are:

--Set the object variable to a global variable so that it can be called in other ways to set their properties

--Set a global variable index, which is 0 by default, and then invoke different data by adding a decrease to the index value and combining the switch.

--Initialize the page by invoking the change method first, so that the page is fixed in the first frame.

--Use the button's Enabled property to set whether the button can be clicked, and then combine the values of index in the 1th Zhang and 5th Zhang Shi respectively to set the previous and Next buttons to be gray and not clickable. Of course, when initializing the page, you should also decide to set the previous button to Gray.

The change method and the Btncheck method here are the product of code refactoring, because both methods need to be called in the Preone and Nextone methods, so in order to avoid repeating the code, the duplicated parts are encapsulated as a method.

#import "ViewController.h"//To define some objects as global variables, so that @interface Viewcontroller () {UIButton *btnpre can be called in multiple methods;    UIButton *btnnext;    UILabel *numlabel;    UILabel *desclabel;    Uiimageview *imgview1; int index1;}    @end @implementation viewcontroller-(void) viewdidload {Btnpre=[uibutton buttonwithtype:uibuttontyperoundedrect];    Btnpre.frame=cgrectmake (50, 150, 60, 30);    [Btnpre settitle:@ "on a" forstate:uicontrolstatenormal];    [Btnpre addtarget:self Action: @selector (PreOne) forcontrolevents:uicontroleventtouchupinside];    [Self.view Addsubview:btnpre];    Btnnext=[uibutton Buttonwithtype:uibuttontyperoundedrect];    Btnnext.frame=cgrectmake (250, 150, 60, 30);    [Btnnext settitle:@ "Next" forstate:uicontrolstatenormal];    [Btnnext addtarget:self Action: @selector (Nextone) forcontrolevents:uicontroleventtouchupinside];        [Self.view Addsubview:btnnext];    Numlabel=[[uilabel Alloc]init];    Numlabel.frame=cgrectmake (170, 50, 100, 30);      [Self.view Addsubview:numlabel];  Desclabel=[[uilabel Alloc]init];    Desclabel.frame=cgrectmake (110, 300, 200, 30);        [Self.view Addsubview:desclabel];    Imgview1=[[uiimageview Alloc]init];    Imgview1.frame=cgrectmake (130, 100, 100, 100);        [Self.view Addsubview:imgview1];        Since the index at the beginning is 0, we call the change method directly, which is equivalent to the first frame page paged out to initialize the page [self change];        Btnpre.enabled= (index1!=0);    [Super Viewdidload]; Do any additional setup after loading the view, typically from a nib.}    -(void) preone{index1--;    [Self btncheck]; [Self change];}    -(void) nextone{index1++;    [Self btncheck]; [Self change];} The Enabled property of the button and, if no, turns gray.    In fact, the following statement is a trinocular operation pushed to and-(void) btncheck{btnpre.enabled= (index1!=0); Btnnext.enabled= (index1!=4);}            -(void) change{switch (index1) {case 0: [email protected] "1/5";            [Email protected] "This was the letter A";            Imgview1.image=[uiimage imagenamed:@ "A.png"];        Break Case 1: [email protected] "2/5";           [Email protected] "This was the letter B";            Imgview1.image=[uiimage imagenamed:@ "B.png"];        Break            Case 2: [email protected] "3/5";            [Email protected] "This was the letter C";            Imgview1.image=[uiimage imagenamed:@ "C.png"];        Break            Case 3: [email protected] "4/5";            [Email protected] "This was the letter D";            Imgview1.image=[uiimage imagenamed:@ "D.png"];        Break            Case 4: [email protected] "5/5";            [Email protected] "This was the letter E";            Imgview1.image=[uiimage imagenamed:@ "E.png"];        Break    Default:break; }} @end

(2) Transform the switch: Use the formatted output to refactor the code: the second line of code instead of the 5 lines commented out.

-(void) change{numlabel.text=[nsstring stringwithformat:@ "%d/%d", index1+1,5];            Switch (index1) {case 0://[email protected] "1/5";            [Email protected] "This was the letter A";            Imgview1.image=[uiimage imagenamed:@ "A.png"];        Break            Case 1://[email protected] "2/5";            [Email protected] "This was the letter B";            Imgview1.image=[uiimage imagenamed:@ "B.png"];        Break            Case 2://[email protected] "3/5";            [Email protected] "This was the letter C";            Imgview1.image=[uiimage imagenamed:@ "C.png"];        Break            Case 3://[email protected] "4/5";            [Email protected] "This was the letter D";            Imgview1.image=[uiimage imagenamed:@ "D.png"];        Break            Case 4://[email protected] "5/5";            [Email protected] "This was the letter E"; Imgview1.image=[uIImage imagenamed:@ "E.png"];        Break    Default:break; }}

(3) using dictionaries and arrays to separate the data, and to achieve the deletion of data and the independence between the code, that is, after adding or subtracting data, we do not need to modify the display "total number of pages" and other such code, but the increase or decrease of data still need to be achieved by adding or subtracting code. (Define a global variable at the beginning Nsarray *arr1)

-(void) Viewdidload {...    Nsmutabledictionary *dic1=[nsmutabledictionary Dictionary];    dic1[@ "icon"][email protected] "a.png";        dic1[@ "desc"][email protected] "This was the letter A";    Nsmutabledictionary *dic2=[nsmutabledictionary Dictionary];    dic2[@ "icon"][email protected] "b.png";        dic2[@ "desc"][email protected] "This was the letter B";    Nsmutabledictionary *dic3=[nsmutabledictionary Dictionary];    dic3[@ "icon"][email protected] "c.png";        dic3[@ "desc"][email protected] "This was the letter C";    Nsmutabledictionary *dic4=[nsmutabledictionary Dictionary];    dic4[@ "icon"][email protected] "d.png";        dic4[@ "desc"][email protected] "This is the letter D";    Nsmutabledictionary *dic5=[nsmutabledictionary Dictionary];    dic5[@ "icon"][email protected] "e.png";        dic5[@ "desc"][email protected] "This was the letter E";    Arr1=[nsarray arraywithobjects:dic1,dic2,dic3,dic4,dic5, nil]; The above code needs to be added to the, otherwise this initialization is a [self change] with no data to initialize;        Btnpre.enabled= (index1!=0);    [Super Viewdidload]; Do any additional setup after loading the view, typically from a nib.}

Once the data has been initialized, other places can be simplified, such as counting the number of pages, such as fetching data, you can use dictionaries and arrays to fetch data:

-(void) btncheck{    btnpre.enabled= (index1!=0);    Btnnext.enabled= (index1!=arr1.count-1);//Count the number of pages related code}

-(void) change{    numlabel.text=[nsstring stringwithformat:@ "%d/%d", index1+1,5];    Take out the corresponding data    nsdictionary *DIC=ARR1[INDEX1];    Set icon image    imgview1.image=[uiimage imagenamed:dic[@ "icon"];    Set description text    desclabel.text=dic[@ "desc"];}

The advantage of the above step is that when we add or subtract the data, we only need to increase or decrease the new dic6 and so on, and then put dic6 and so on into the array arr1. The rest of the place does not need to manually modify the numbers, because the place where we refer to the numbers is using the Count property of the array, where the reference data is using the relevant properties of the array and the dictionary, not the dead, but the live.


(4) Using macro variables to avoid the possibility of errors in code, especially in multi-person collaborative development, the use of macro variable hints can reduce the possibility of false input.

#define Kiconkey @ "icon" #define KDESCRIP @ "desc"

So all other responses should replace the macro variable.


(5) The use of property to create variables, note that although the teacher said the proposed control objects with weak, and general objects with strong, but found that using weak can not instantiate the object, so here temporarily or with strong, and so on to find out why. The following variables of the response can be replaced with _**** or self.*** instead. It is recommended to use the latter here.

@interface Viewcontroller () {//    UIButton *btnpre;//    UIButton *btnnext;//    UILabel *numlabel;//    UILabel *desclabel;//    uiimageview *imgview1;//    int index1;} @property (Nonatomic,retain) UIButton *btnpre; @property (nonatomic,retain) UIButton *btnnext; @property (Nonatomic, Retain) UILabel *numlabel, @property (nonatomic,retain) UILabel *desclabel; @property (nonatomic,strong) Uiimageview * ImgView1; @property (Nonatomic,strong) Nsarray *arr1; @property (nonatomic,assign) int index1; @end

(6) Delay loading, lazy loading. The load data is initialized only when needed. In other words, we can put the initialization of the data type property in the getter method of this data, and make a judgment whether to reload.

Our default Arr1 getter method is:

-(Nsarray *) arr1{    return _arr1;}

Modified as follows, that is, if the array is loaded with data, it is not loaded repeatedly, and it is loaded with the SELF.ARR1 call to it, which is lazy loading:

-(Nsarray *) arr1{if (_arr1==nil) {///here with _ARR1 instead of SELF.ARR1 is to avoid the dead loop, because SELF.ARR1 is also called this function, will always call itself Nsmutabledictionar        y *dic1=[nsmutabledictionary dictionary];        Dic1[kiconkey][email protected] "a.png";                Dic1[kdescrip][email protected] "This was the letter A";        Nsmutabledictionary *dic2=[nsmutabledictionary Dictionary];        Dic2[kiconkey][email protected] "b.png";                Dic2[kdescrip][email protected] "This was the letter B";        Nsmutabledictionary *dic3=[nsmutabledictionary Dictionary];        Dic3[kiconkey][email protected] "c.png";                Dic3[kdescrip][email protected] "the letter C";        Nsmutabledictionary *dic4=[nsmutabledictionary Dictionary];        Dic4[kiconkey][email protected] "d.png";                Dic4[kdescrip][email protected] "This was the letter D";        Nsmutabledictionary *dic5=[nsmutabledictionary Dictionary];        Dic5[kiconkey][email protected] "e.png"; DIc5[kdescrip][email protected] "This is the letter E";    _arr1=[nsarray arraywithobjects:dic1,dic2,dic3,dic4,dic5, nil]; } return _ARR1;}

(7) Further: The data is stored independently in the plist, and the subsequent increase or decrease in data only modifies the plist file, without the need to add or subtract data in the code.

Create the plist file first:



Then, in the Code reference, the commented out of those data has been stored in the plist file, with the bottom of the few lines to use the plist file can be, after the increase or decrease in data, as long as the change plist file, do not need to change the code:

-(Nsarray *) arr1{if (_arr1==nil) {//nsmutabledictionary *dic1=[nsmutabledictionary dictionary];//dic1[        Kiconkey][email protected] "a.png";//dic1[kdescrip][email protected] "the letter A";//        Nsmutabledictionary *dic2=[nsmutabledictionary dictionary];//dic2[kiconkey][email protected] "b.png";// Dic2[kdescrip][email protected] "the letter B";///Nsmutabledictionary *dic3=[nsmutable Dictionary dictionary];//dic3[kiconkey][email protected] "c.png";//dic3[kdescrip][email protected ] "the letter C";///Nsmutabledictionary *dic4=[nsmutabledictionary dictionary];//Dic4[kico        Nkey][email protected] "d.png";//dic4[kdescrip][email protected] "the letter D";///        Nsmutabledictionary *dic5=[nsmutabledictionary dictionary];//dic5[kiconkey][email protected] "e.png";// dic5[kdescrip][email&Nbsp;protected] "This is the letter E";                _arr1=[nsarray arraywithobjects:dic1,dic2,dic3,dic4,dic5, nil];        Get Mainbundle, i.e. program Main folder NSBundle *path=[nsbundle Mainbundle];        Use the obtained mainbundle to find the file, return to the path nsstring *pathfile=[path pathforresource:@ "Imgdata" oftype:@ "plist"];    _arr1=[nsarray Arraywithcontentsoffile:pathfile]; } return _ARR1;}

(8) Supplement: How to view this Mainbundle resource library?

nsbundle* Path=[nsbundle Mainbundle] is the path to the repository, and the return of the NSBundle object is actually a path through which all the resources in the repository can be accessed. Where does it actually fit in? Do not need to search the Internet, directly with NSLog (@ "%@", path); Print out this path is not OK.


Follow the path above to find this Hello.app package >>> right click to display the contents of the package. Done.


(9) The size of the picture is different, how is it good?

Generally we will give Uiimageview set a fixed width, but the picture if there are large and small how to do? Need to call "content mode" Contentmode This property, that is, adjust the contents of uiimageview inside how to zoom. The general default is to stretch the picture until it fills the entire uiviewview. This usually changes the aspect ratio of the picture, making the picture distorted. We commonly used, in the case of maintaining the picture aspect ratio, as far as possible to fill the uiimageview can be, this property and value is (why the above code is not added, because we do the time to set the picture is 100*100,uiimageview is also 100* 100, so you don't need to use this property):

Self.imgview1.contentmode=uiviewcontentmodescaleaspectfit;

(10) Too much text, how to set the word wrap?

To describe the text of the Desclabel as an example, we have not a lot of text in this case, and gave the desclabel width of 200, enough to use, all only one row. If we set the width to 100, we find that the display does not fit, and finally there is a ... Represents omitting content. Set multiple lines, there is a Numberofline property, you can set the specific number of 2,3,4 and so on, you can also directly use 0, indicating that it does not matter how many rows.

Note that when setting multiple lines, your desclabel height should be sufficient, or it will still be displayed ... Ellipsis. We were 30 in height and changed to 60.

    Self.desclabel.frame=cgrectmake (a);    self.desclabel.numberoflines=0;


Summary: Do it yourself. Although all understand the principle, but the real operation, will encounter some very small but very important problem, a solution, such accumulation is the difference between novice and veteran.


"iOS Dev-44" Talk about iOS code refactoring with cases: merging, formatting output, macro variables, storing data using an array dictionary, and using Plist's ultimate knowledge

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.