天天看點

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系

轉載自:http://blog.csdn.net/weisubao/article/details/40075409

本次九宮格案例:

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系

(1)導入app.plist和各種圖檔素材,友善後續開發。實際開發中,也是如此。

(2)把plist中數組導入進來。

——因為本案例中app.plist最終是一個數組,數組裡面是字典。是以我們需要一個數組類型來接受這個plist檔案。

——我們利用之前掌握的在變量的getter中進行延遲加載資料。

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. #import "ViewController.h"  
  2. @interface ViewController ()  
  3. @property(nonatomic,strong) NSArray *arr1;  
  4. @end  
  5. @implementation ViewController  
  6. - (void)viewDidLoad {  
  7.     self.arr1;  
  8.     [super viewDidLoad];  
  9. }  
  10. -(NSArray *)arr1{  
  11.     if (_arr1==nil) {  
  12.         NSString *path=[[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];  
  13.         _arr1=[NSArray arrayWithContentsOfFile:path];  
  14.         NSLog(@"%@",_arr1);  
  15.     }  
  16.     return _arr1;  
  17. }  
  18. @end  

輸出結果是:

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1.       {  
  2.       icon = "icon_00";  
  3.       name = "\U5929\U5929\U9177\U8dd1";  
  4.   },  
  5.       {  
  6.       icon = "icon_01";  
  7.       name = "\U5168\U6c11\U98de\U673a\U5927\U6218";  
  8.   },  
  9. ……  

icon後面就是icon的名稱,name後面也是name的名稱,隻不過中文被轉換成了Unicode形式,一個漢字就是一個\U****。

(3)九宮格計算

——關鍵在于利用 / 和 % 運算得到元素所在的行和列,注意%符号運算前後不能有CGFloat,都換成int類型較好。

——CGFloat其實就是float和double的集合。所有用float和double的地方幾乎都可以用CGFloat。會根據目前系統自動解析,如果是32位系統,則用float,如果是64位系統,則解析成double。

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. - (void)viewDidLoad {  
  2.     //定義總列數、每個九宮格的寬高  
  3.     int totalColumns=3;  
  4.     CGFloat appW=90;  
  5.     CGFloat appH=100;  
  6.     //定義水準和垂直方面的間距  
  7.     CGFloat marginX=(self.view.frame.size.width-totalColumns*appW)/(totalColumns+1);  
  8.     CGFloat marginY=20;  
  9.     //根據arr1中資料數量來初始化并加載一個一個的UIVIew  
  10.     for (int index=0; index<self.arr1.count; index++) {  
  11.         //計算這個app在幾行幾列  
  12.         int row=index/totalColumns;  
  13.         int col=index%totalColumns;  
  14.         //建立UIView  
  15.         UIView *appView=[[UIView alloc]init];  
  16.         //根據一些計算,确定不同UIView的位置  
  17.         appView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);  
  18.         appView.backgroundColor=[UIColor redColor];  
  19.         [self.view addSubview:appView];  
  20.     }  
  21.     [super viewDidLoad];  
  22.     // Do any additional setup after loading the view, typically from a nib.  
  23. }  

(4)往每個appView裡面添加一個UIImageView、UIlabel和UIButton。直接在for循環中添加,即建立UIView *appView的時候順便把它裡面的東西也建立了。

——其中,UIImageView裡的圖檔用到取得圖檔的名稱,這個可以存放在plist裡面,我們把_arr1裡對應的字典取出來使用即可。

——重點是,UIButton的字型大小無法直接設定,而是用到UIbutton裡的子視圖titleLabel來設定。(因為UIButton裡面其實封裝了兩個子視圖控件,一個是裝文字的UILabel *titleLabel,一個裝圖檔的UIImageView *imageView)

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1.     for (int index=0; index<self.arr1.count; index++) {  
  2.         //計算這個app在幾行幾列  
  3.         int row=index/totalColumns;  
  4.         int col=index%totalColumns;  
  5.         //建立UIView  
  6.         UIView *appView=[[UIView alloc]init];  
  7.         //根據一些計算,确定不同UIView的位置  
  8.         appView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);  
  9. //        appView.backgroundColor=[UIColor redColor];  
  10.         [self.view addSubview:appView];  
  11.         //根據索引拿到plist每個字典的資料  
  12.         NSDictionary *appDic=_arr1[index];  
  13.         //往appView裡增加子控件icon  
  14.         //根據字典拿到裡面的icon名稱  
  15.         UIImageView *appIcon=[[UIImageView alloc]init];  
  16.         CGFloat iconW=65;  
  17.         CGFloat iconH=65;  
  18.         CGFloat iconX=(appW-iconW)/2;  
  19.         CGFloat iconY=0;  
  20.         appIcon.frame=CGRectMake(iconX, iconY, iconW, iconH);  
  21.         appIcon.image=[UIImage imageNamed:appDic[@"icon"]];  
  22.         [appView addSubview:appIcon];  
  23.         //往appView裡增加子控件label  
  24.         UILabel *appLabel=[[UILabel alloc]init];  
  25.         CGFloat labelW=appW;  
  26.         CGFloat labelH=20;  
  27.         CGFloat labelX=(appW-labelW)/2;  
  28.         CGFloat labelY=iconY+iconH;  
  29.         appLabel.frame=CGRectMake(labelX, labelY, labelW, labelH);  
  30.         appLabel.text=appDic[@"name"];  
  31.         appLabel.textAlignment=NSTextAlignmentCenter;  
  32.         appLabel.font=[UIFont systemFontOfSize:14];  
  33.         [appView addSubview:appLabel];  
  34.         //往appView裡增加子控件button  
  35.         UIButton *appBtn=[[UIButton alloc]init];  
  36.         CGFloat btnW=65;  
  37.         CGFloat btnH=26;  
  38.         CGFloat btnX=(appW-btnW)/2;  
  39.         CGFloat btnY=labelY+labelH;  
  40.         appBtn.frame=CGRectMake(btnX, btnY, btnW, btnH);  
  41.         [appBtn setTitle:@"下載下傳" forState:UIControlStateNormal];  
  42.         appBtn.titleLabel.font=[UIFont systemFontOfSize:14];  
  43.         [appBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];  
  44.         [appBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateNormal];  
  45.         [appView addSubview:appBtn];  
  46.     }  

(5)最重要的:字典轉模型

使用字典的壞處:需要用key值調取和設定資料,有時候會出錯,雖然可以用宏變量改進,但是更要命的寫錯了key值,沒有錯誤提示。

模型:嚴格叫做模型資料。核心就是我們把字典當成一個對象,字典裡面的幾個資料,我們分别轉換成對象的幾個屬性,我們調用和設定資料的時候直接是“對象.屬性”即可。

是以,我們需要建立一個類,這個專門用來存放資料,也就是常說的模型類。

本例中,建立一個JiuGongGe類,在.h中聲明2個變量,和2種初始化方法(規範都是有2種初始化方法,其實核心是一種,第二種還是通過第一種來實作的)。

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. #import <Foundation/Foundation.h>  
  2. @interface JiuGongGe : NSObject  
  3. @property(nonatomic,copy) NSString *name;  
  4. @property(nonatomic,copy) NSString *icon;  
  5. -(instancetype)initWithJiuGongGe:(NSDictionary *)dic;  
  6. +(instancetype)jiuGongGeWith:(NSDictionary *)dic;  
  7. @end  

在JiuGongGe.m中實作(注意寫法,記憶):

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. #import "JiuGongGe.h"  
  2. @implementation JiuGongGe  
  3. -(instancetype)initWithJiuGongGe:(NSDictionary *)dic{  
  4.     if (self=[super init]) {  
  5.         self.name=dic[@"name"];  
  6.         self.icon=dic[@"icon"];  
  7.     }  
  8.     return self;  
  9. }  
  10. +(instancetype)jiuGongGeWith:(NSDictionary *)dic{  
  11.     return [[JiuGongGe alloc]initWithJiuGongGe:dic];  
  12. }  
  13. @end  

其實,我們的小标題是“字典轉模型”,也就是說隻是把字典轉換成模型(對象),原先字典存放在數組中的,然後通過數組[index]一個個調用字典,現在模型(對象)依然存放在數組中。是以我們需要對數組的那個getter方法進行改進:(注意:需要在ViewController.m中#import "JiuGongGe.h",因為要執行個體化對象)

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. -(NSArray *)arr1{  
  2.     if (_arr1==nil) {  
  3.         NSString *path=[[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];  
  4.         NSArray *tmpArr=[NSArray arrayWithContentsOfFile:path];  
  5.         NSMutableArray *muArr1=[[NSMutableArray alloc]init];  
  6.         for (NSDictionary *dict in tmpArr) {  
  7.             JiuGongGe *jiugognge=[JiuGongGe jiuGongGeWith:dict];  
  8.             [muArr1 addObject:jiugognge];  
  9.         }  
  10.         _arr1=muArr1;  
  11.     }  
  12.     return _arr1;  
  13. }  

在ViewDidLoad的那個for循環中,用到的地方都可以用對象.屬性來調用資料了:

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. //根據索引拿到每個對象,此處appDic名稱未改,還是用之前取字典的那個變量,看的不太習慣  
  2. JiuGongGe *appDic=_arr1[index];  
  3. //往appView裡增加子控件icon  
  4. ……  
  5. appIcon.image=[UIImage imageNamed:appDic.icon];  
  6. //往appView裡增加子控件label  
  7. appLabel.text=appDic.name;  

(6)jiuGongGeWith:(NSDictionary *)dic;初始化方法的改進

——裡面用到的類名,可以替換成self。因為防止這個類有子類,如果子類調用jiuGongGeWith:(NSDictionary *)dic;時調用到父類的這個方法,裡面寫得名字還是父類的名字,初始化結果是一個父類的對象,而不是子類的對象。是以用self,誰調用就初始化誰的對象。

(7)id類型和instancetype的說明

——instancetype和id一樣,都是萬能指針。

——iOS建議我們使用instancetype代替id。盡管官方很多init方法的傳回值也是id。

——使用id的好處就是,id是萬能指針,我們不用擔心它的傳回值類型不比對的問題。

——使用id的壞處:也正是因為它是萬能指針,我們可以用任意指針接受這個傳回值,比如NSString *str1=****,NSArray *arr1=****,這句代碼寫出來不會報錯。但是有可能不是我們需要的傳回值類型。

——使用instancetype的好處是,如果我們傳回值是一個對象,那麼你用上面兩個任意指針接受這個傳回值,它會有warning警告,我們用類對象JiuGongGe *jiugognge=***,就不會警告。

——instancetype隻能用在傳回值類型上,不能像id一樣用在參數上。

(8)利用xib圖形化布局減少代碼

xib和storyboard的差別在于,storyboard是描述整個程式界面的,而xib多用于局部重複界面的描述。

比如本例中有12個應用,每個應用的視圖都是一樣的,可以用xib來實作,然後再把xib加載進來即可。

xib的建立(用empty):

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系

在ourXib中布局:

——給UIImageView和UILabel分别設定tag為10和20,友善調用。

——拖動控件到界面中,改變大小時候,UIImageView需要把size設定成Freeform才能調整大小。

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系

ourXib設定好後,就可以調用:

——除了圖檔之外的資源,都需要用[NSBundle mainBundle]來調用。

——調用xib檔案的方法是mainBundle的loadNibNamed方法。

[objc]  view plain copy

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系
  1. for (int index=0; index<self.arr1.count; index++) {  
  2.     //計算這個app在幾行幾列  
  3.     int row=index/totalColumns;  
  4.     int col=index%totalColumns;  
  5.     //根據索引拿到每個對象  
  6.     JiuGongGe *appDic=_arr1[index];  
  7.     NSArray *xibArr=[[NSBundle mainBundle]loadNibNamed:@"ourXib" owner:nil options:nil];  
  8.     UIView *xibView=[xibArr lastObject];  
  9.     xibView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);  
  10.     UIImageView *imgView2=(UIImageView *)[xibView viewWithTag:10];  
  11.     imgView2.image=[UIImage imageNamed:appDic.icon];  
  12.     UILabel *label2=(UILabel *)[xibView viewWithTag:20];  
  13.     label2.text=appDic.name;  
  14.     //添加到主view中  
  15.     [self.view addSubview:xibView];  
  16. }  

(9)xib檔案和nib檔案是什麼關系?

——xib檔案是我們開發者在開發的時候看到的東西;

——而運作在使用者手機裡時,xib檔案會被轉化為nib檔案。

我們可以在iOS Simulator産生的沙盒中檢視。

——找不到資源庫路徑,直接用NSLog(@"%@",[NSBundle mainBundle);把路徑列印出來。

查找發現,這個資源庫中确實有個ourXib.nib檔案,xib檔案确實轉化成nib檔案了。

iOS開發九宮格布局案例:自動布局、字典轉模型運用、id和instancetype差別、xib重複視圖運用及與nib關系