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

來源:互聯網
上載者:User

標籤:style   blog   http   color   io   os   使用   ar   for   

本次九宮格案例:


(1)匯入app.plist和各種圖片素材,方便後續開發。實際開發中,也是如此。


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

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

——我們利用之前掌握的在變數的getter中進行消極式載入資料。

#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
輸出結果是:

        {        icon = "icon_00";        name = "\U5929\U5929\U9177\U8dd1";    },        {        icon = "icon_01";        name = "\U5168\U6c11\U98de\U673a\U5927\U6218";    },  ……


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

(3)九宮格計算

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

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

- (void)viewDidLoad {    //定義總列數、每個九宮格的寬高    int totalColumns=3;    CGFloat appW=90;    CGFloat appH=100;    //定義水平和垂直方面的間距    CGFloat marginX=(self.view.frame.size.width-totalColumns*appW)/(totalColumns+1);    CGFloat marginY=20;        //根據arr1中資料數量來初始化並載入一個一個的UIVIew    for (int index=0; index<self.arr1.count; index++) {        //計算這個app在幾行幾列        int row=index/totalColumns;        int col=index%totalColumns;        //建立UIView        UIView *appView=[[UIView alloc]init];        //根據一些計算,確定不同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)往每個appView裡面添加一個UIImageView、UIlabel和UIButton。直接在for迴圈中添加,即建立UIView *appView的時候順便把它裡面的東西也建立了。

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

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

    for (int index=0; index<self.arr1.count; index++) {        //計算這個app在幾行幾列        int row=index/totalColumns;        int col=index%totalColumns;        //建立UIView        UIView *appView=[[UIView alloc]init];        //根據一些計算,確定不同UIView的位置        appView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);//        appView.backgroundColor=[UIColor redColor];        [self.view addSubview:appView];                //根據索引拿到plist每個字典的資料        NSDictionary *appDic=_arr1[index];                //往appView裡增加子控制項icon        //根據字典拿到裡面的icon名稱        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];                //往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];                //往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:@"下載" 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)最重要的:字典轉模型

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

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

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

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

#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

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

#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

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

-(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;}

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

        //根據索引拿到每個對象,此處appDic名稱未改,還是用之前取字典的那個變數,看的不太習慣        JiuGongGe *appDic=_arr1[index];                //往appView裡增加子控制項icon        ……        appIcon.image=[UIImage imageNamed:appDic.icon];                //往appView裡增加子控制項label        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):


在ourXib中布局:

——給UIImageView和UILabel分別設定tag為10和20,方便調用。

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


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

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

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

    for (int index=0; index<self.arr1.count; index++) {        //計算這個app在幾行幾列        int row=index/totalColumns;        int col=index%totalColumns;                //根據索引拿到每個對象        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;        //添加到主view中        [self.view addSubview:xibView];    }

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

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

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

我們可以在iOS Simulator產生的沙箱中查看。

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

尋找發現,這個資產庫中確實有個ourXib.nib檔案,xib檔案確實轉化成nib檔案了。



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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.