標籤:
我們今天的情況下是第一個例子,下面的5一來通過切換頁上一頁下一頁:
(1)第一步,基本是以非常傻非常直接的方式來建立。這裡用到的主要點有:
——把物件變數設定為全域變數使得能夠在其它方法中調用來設定它們的屬性
——設定了一個全域變數index,預設是0。然後通過添加降低這個index值並結合switch來調用不同的資料。
——利用先調用一次change方法初始化頁面。使得頁面定格在第一幀。
——利用button的enabled屬性來設定button能否夠被點擊,然後結合index的值分別在第1張和第5張時分別把上一張和下一張button設定為灰色不可點擊。當然初始化頁面的時候也要推斷一下把上一張button設定為灰色。
——這裡的change方法和btnCheck方法都是代碼重構的產物,由於這兩個方法都須要在preOne和nextOne方法中被調用,所以為了避免反覆代碼,所以把這些反覆的部分都封裝成了方法。
#import "ViewController.h"//把一些對象定義成全域變數。這樣能夠多個方法中調用@interface ViewController (){ UIButton *btnPre; 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:@"上一張" 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:@"下一張" 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]; //由於一開始的index為0。所以我們直接調用change方法,相當於把第一幀的頁面調出來初始化頁面 [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];}//按鈕的enabled屬性,假設是NO,則變成灰色。事實上下面語句是三目運算推到而來-(void)btnCheck{ btnPre.enabled=(index1!=0); btnNext.enabled=(index1!=4);}-(void)change{ switch (index1) { case 0: [email protected]"1/5"; [email protected]"This is the letter A"; imgView1.image=[UIImage imageNamed:@"a.png"]; break; case 1: [email protected]"2/5"; [email protected]"This is the letter B"; imgView1.image=[UIImage imageNamed:@"b.png"]; break; case 2: [email protected]"3/5"; [email protected]"This is the letter C"; imgView1.image=[UIImage imageNamed:@"c.png"]; break; case 3: [email protected]"4/5"; [email protected]"This is the letter D"; imgView1.image=[UIImage imageNamed:@"d.png"]; break; case 4: [email protected]"5/5"; [email protected]"This is the letter E"; imgView1.image=[UIImage imageNamed:@"e.png"]; break; default: break; }}@end
(2)對switch部分進行改造:利用格式化輸出重構代碼:用第二行代碼取代凝視掉的那5行代碼。
-(void)change{ numLabel.text=[NSString stringWithFormat:@"%d/%d",index1+1,5]; switch (index1) { case 0: //[email protected]"1/5"; [email protected]"This is the letter A"; imgView1.image=[UIImage imageNamed:@"a.png"]; break; case 1: //[email protected]"2/5"; [email protected]"This is the letter B"; imgView1.image=[UIImage imageNamed:@"b.png"]; break; case 2: //[email protected]"3/5"; [email protected]"This is the letter C"; imgView1.image=[UIImage imageNamed:@"c.png"]; break; case 3: //[email protected]"4/5"; [email protected]"This is the letter D"; imgView1.image=[UIImage imageNamed:@"d.png"]; break; case 4: //[email protected]"5/5"; [email protected]"This is the letter E"; imgView1.image=[UIImage imageNamed:@"e.png"]; break; default: break; }}
(3)利用字典和數組把資料單獨出來,並實現資料的刪減和代碼之間的獨立,即增減資料後,不須要改動我們顯示“總頁數”等這些代碼,但增減資料仍須要通過增減代碼來實現。(在開頭定義一個全域變數NSArray *arr1)
- (void)viewDidLoad { …… NSMutableDictionary *dic1=[NSMutableDictionary dictionary]; dic1[@"icon"][email protected]"a.png"; dic1[@"desc"][email protected]"This is the letter A"; NSMutableDictionary *dic2=[NSMutableDictionary dictionary]; dic2[@"icon"][email protected]"b.png"; dic2[@"desc"][email protected]"This is the letter B"; NSMutableDictionary *dic3=[NSMutableDictionary dictionary]; dic3[@"icon"][email protected]"c.png"; dic3[@"desc"][email protected]"This is 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 is the letter E"; arr1=[NSArray arrayWithObjects:dic1,dic2,dic3,dic4,dic5, nil]; //以上代碼須要加入在self change上。否則這個初始化是沒有資料能夠初始化的 [self change]; btnPre.enabled=(index1!=0); [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.}
初始化了資料之後。其它地方都能夠進行簡化了。比方計算頁數,比方取資料,就能夠利用字典和數組來取資料:
-(void)btnCheck{ btnPre.enabled=(index1!=0); btnNext.enabled=(index1!=arr1.count-1);//計算頁數的相關代碼}
-(void)change{ numLabel.text=[NSString stringWithFormat:@"%d/%d",index1+1,5]; //取出相應的資料 NSDictionary *dic=arr1[index1]; //設定icon圖片 imgView1.image=[UIImage imageNamed:dic[@"icon"]]; //設定描寫敘述文字 descLabel.text=dic[@"desc"];}
以上一步的優點在於我們增減資料的時候僅僅須要在增減新的dic6等等。然後把dic6之類的加入到數組arr1中就可以。
其餘地方不須要手動改動數字,由於我們引用數位地方是用了數組的count屬性。引用資料的地方使用了數組和字典的相關屬性,不是寫死的,而是活的。
(4)利用宏變數避免代碼出現錯誤的可能性,尤其是在多人協作開發時。利用宏變數的提示可降低誤輸入的可能。
#define kICONKEY @"icon"#define kDESCRIP @"desc"
所以其它響應的地方都應該替換成宏變數。
(5)利用property建立變數,注意。儘管老師說建議控制項對象用weak。而一般對象用strong,可是發現。使用weak根本無法執行個體化對象,所以此處臨時還是用strong。等查明原因再說。
響應的以下的變數都能夠用_****取代或者用self.***取代。
建議此處用後者。
@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)延遲載入,懶載入。僅僅有須要的時候才初始化載入資料。
也就是說,我們能夠把資料型的屬性的初始化放在這個資料的getter方法中。且做一個推斷是否要又一次載入。
我們預設的arr1的getter方法是:
-(NSArray *)arr1{ return _arr1;}
改動為例如以下。即假設這個數組載入過資料,則不用反覆載入,並且是用self.arr1調用到它的時候才載入,這就是延遲載入:
-(NSArray *)arr1{ if (_arr1==nil) {//此處用_arr1而不用self.arr1是避免死迴圈。由於self.arr1也是調用這個函數。會一直迴圈調用自身 NSMutableDictionary *dic1=[NSMutableDictionary dictionary]; dic1[kICONKEY][email protected]"a.png"; dic1[kDESCRIP][email protected]"This is the letter A"; NSMutableDictionary *dic2=[NSMutableDictionary dictionary]; dic2[kICONKEY][email protected]"b.png"; dic2[kDESCRIP][email protected]"This is the letter B"; NSMutableDictionary *dic3=[NSMutableDictionary dictionary]; dic3[kICONKEY][email protected]"c.png"; dic3[kDESCRIP][email protected]"This is the letter C"; NSMutableDictionary *dic4=[NSMutableDictionary dictionary]; dic4[kICONKEY][email protected]"d.png"; dic4[kDESCRIP][email protected]"This is 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)再進一步:把資料獨立存放在plist中,以後增減資料僅僅是改動plist檔案,而不須要在代碼中增減資料。
先建立plist檔案:
然後,在代碼中引用。凝視掉的那些資料都已經存放在plist檔案裡了。用最以下的幾行來使用plist檔案就可以,以後有增減資料,僅僅要修改plist檔案,不須要修改代碼:
-(NSArray *)arr1{ if (_arr1==nil) {// NSMutableDictionary *dic1=[NSMutableDictionary dictionary];// dic1[kICONKEY][email protected]"a.png";// dic1[kDESCRIP][email protected]"This is the letter A";// // NSMutableDictionary *dic2=[NSMutableDictionary dictionary];// dic2[kICONKEY][email protected]"b.png";// dic2[kDESCRIP][email protected]"This is the letter B";// // NSMutableDictionary *dic3=[NSMutableDictionary dictionary];// dic3[kICONKEY][email protected]"c.png";// dic3[kDESCRIP][email protected]"This is the letter C";// // NSMutableDictionary *dic4=[NSMutableDictionary dictionary];// dic4[kICONKEY][email protected]"d.png";// dic4[kDESCRIP][email protected]"This is 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]; //取得mainBundle。即程式主目錄 NSBundle *path=[NSBundle mainBundle]; //用取得的mainBundle來尋找檔案,返迴路徑 NSString *pathFile=[path pathForResource:@"imgdata" ofType:@"plist"]; _arr1=[NSArray arrayWithContentsOfFile:pathFile]; } return _arr1;}
(8)補充:怎麼查看這個mainBundle資產庫?
NSBundle* path=[NSBundle mainBundle]就是拿到這個資產庫的路徑。返回的是NSBundle對象,事實上是一個路徑,能夠通過這個來訪問資產庫裡面的全部資源。事實上它詳細放在哪裡?無須上網尋找,直接用NSLog(@"%@",path);把這個路徑列印出來不就ok了嘛。
NSBundle </Users/Andy/Library/Developer/CoreSimulator/Devices/64EDA842-5B0C-448D-BF2B-B063D09B60CB/data/Containers/Bundle/Application/E0E6FE95-99D1-4F70-84CD-D73059EA71DF/hello.app>
順著上面這個路徑就找到了這個hello.app包>>>右擊顯示包內容。
大功告成。
(9)圖片的大小不一樣,怎樣是好?
一般我們會給UIImageView設定好固定的寬高,可是圖片假設有大有小怎麼辦?須要用到調用“內容模式”contentMode這個屬性。即調整UIImageView裡面內容怎麼縮放擺放的。
一般預設的是展開圖片直至填滿整個UIViewView。這樣一般會改變圖片的寬高比,使得圖片變形。我們一般經常使用的時,在保持圖片寬高比的情況下,儘可能的填充這個UIImageView就可以,這個屬性以及值就是(以上代碼為什麼沒有加入,由於我們做得時候就設定了圖片都是100*100,UIImageView也是100*100,所以不須要用到這個屬性):
self.imgView1.contentMode=UIViewContentModeScaleAspectFit;
(10)文字太多。自己主動換行怎麼設定?
以描寫敘述文字的descLabel為例。我們本案例中文字並非非常多,且給了這個descLabel寬度200,足夠用。全部僅僅有一行。假設我們把寬度設定為100,就發現顯示不下。最後有個...表示省略內容。設定多行,有個numberOfLine屬性。你能夠設定詳細的2,3,4等行數數字。也能夠直接用0,表示無所謂多少行。
須要注意的時,設定多行的時候,你的descLabel高度要足夠,不然依舊是顯示...省略符號。我們原先是30的高度,此處改成了60。
self.descLabel.frame=CGRectMake(110, 300, 100, 60); self.descLabel.numberOfLines=0;
總結:要自己動手。儘管都明確當中原理,可是真正操作起來,會遇到一些非常小可是非常重要的問題,一個一個的解決定,這種積累,預計新手和差異老兵。
著作權聲明:本文部落格原創文章。部落格,未經同意,不得轉載。
【iOS發展-44】通過案例談iOS重構:合并、格式化輸出、宏觀變數、使用數組來儲存資料字典,而且使用plist最終的知識