咱們繼續學習Table View的內容,此次主要是針對UITableViewCell,在前一篇的例子中咱們已經使用過UITableViewCell,一個默認的UITableViewCell包含imageView、textLabel、detailTextLabel等屬性,可是不少時候這些默認的屬性並不能知足須要,其實更多的時候咱們想本身制定UITableViewCell的內容,這篇學習的就是制定本身的UITableViewCell。iphone
UITableViewCell繼承自UIView,所以它能夠加載任意的subView在上面,基於這一點,咱們就能夠定製本身的UITableViewCell了。制定UITableViewCell有2種方法,一種是寫代碼生成UITableViewCell控件上的內容,另外一種是拖控件到一個UITableViewCell控件上,這兩種方法都會用一個例子來進行說明。佈局
首先咱們使用code的方法,來定製本身的UITableViewCell學習
1)建立一個新的項目,template選擇Single View Application,命名爲Cells this
2)添加Table View,鏈接delegate和data source到File's Owner 選中BIDController.xib文件,從Object Library中拖一個Table View到view上,而後選中view中的table view,打開Connections Inspector,拖動dataSource和delegate右邊的小圓圈到File's Owner上 atom
3)添加Cell 在Project navigator中選中Cells文件夾,而後command+N,添加一個新的文件。在彈出的對話框中,左邊選擇Cocoa Touch,右邊選擇Objective-C,而後點擊Next spa
在下一個對話框中把Class命名爲BIDNameAndColorCell,Subclass of選擇UITableViewCell,而後點擊Next 3d
在下一個對話框中選擇Create,完成建立 code
BIDNameAndColor文件繼承自UITableViewCell,咱們將先對其進行定製,添加一些咱們須要的控件,當BIDViewController中調用table cell的時候,就直接調用這個文件便可。對象
4)添加BIDNameAndColorCell代碼 打開BIDNameAndColorCell.h文件,添加以下代碼blog
#import <UIKit/UIKit.h>
@interface BIDNameAndColorCell : UITableViewCell @property (copy, nonatomic) NSString *name; @property (copy, nonatomic) NSString *color; @end
咱們將在table view cell中顯示2個字符串,一個是name,另外一個是color,顯示的內容會從以後定義的NSArray中讀取。(注意,咱們這裏使用的是copy,而不是一般使用的strong,使用copy的好處是不會改變原有的字符串中的內容,固然在這裏咱們也不會改變字符串的內容,你若是使用了strong也問題不大,不過書上的建議是若是一個property是NSString,最好使用copy)
接着編輯BIDNameAndColorCell.m文件,添加下面的code
#import "BIDNameAndColorCell.h" #define kNameValueTag 1 #define kColorValueTag 2 @implementation BIDNameAndColorCell @synthesize name; @synthesize color;
首先添加2個常量kNameValueTag和kColorValueTag,這2個常量用來標識table view cell中的name和color。接着就是name和color的synthesize了,和以前例子中的同樣。
下面修改BIDNameAndColorCell.m中已存在的initWithStyle:reuseIdentifier:方法
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization code CGRect nameLabelRect = CGRectMake(0, 5, 70, 15); UILabel *nameLabel = [[UILabel alloc] initWithFrame:nameLabelRect]; nameLabel.textAlignment = UITextAlignmentRight; nameLabel.text = @"Name:"; nameLabel.font = [UIFont boldSystemFontOfSize:12]; [self.contentView addSubview:nameLabel]; CGRect colorLabelRect = CGRectMake(0, 26, 70, 15); UILabel *colorLabel = [[UILabel alloc] initWithFrame:colorLabelRect]; colorLabel.textAlignment = UITextAlignmentRight; colorLabel.text = @"Color:"; colorLabel.font = [UIFont boldSystemFontOfSize:12]; [self.contentView addSubview:colorLabel]; CGRect nameValueRect = CGRectMake(80, 5, 200, 15); UILabel *nameValue = [[UILabel alloc]initWithFrame:nameValueRect]; nameValue.tag = kNameValueTag; [self.contentView addSubview:nameValue]; CGRect colorValueRect = CGRectMake(80, 25, 200, 15); UILabel *colorValue = [[UILabel alloc]initWithFrame:colorValueRect]; colorValue.tag = kColorValueTag; [self.contentView addSubview:colorValue]; } return self; }
上面的代碼應該仍是比較容易理解的吧,建立了4個UILabel,設置完UILabel的屬性後,把他們加入到UITableViewCell中,table view cell有一個默認的view叫作contentView,contenView負責容納其餘的subView,所以上面code中所建立的4個UILabel都會添加到contentView中,使用的語句是[self.contentView addSubview:colorValue]
再說一下上面建立的4個UILabel在這個例子中的做用,nameLabel和colorLabel的做用是純粹的Label,它們的值不會在改變,在這隻它們屬性的使用已經分別爲它們賦值了。nameValue和colorValue這2個label是用來顯示NSArray中的值的,這也是爲何只有這2個label會有property,由於它們須要改變值。另外在code中還未這2個label制定了tag,這個tag的具體做用是經過它來標識具體的label,添加下面的code,就會有所瞭解。
- (void)setName:(NSString *)n { if(![n isEqualToString:name]) { name = [n copy]; UILabel *nameLabel = (UILabel *)[self.contentView viewWithTag:kNameValueTag]; nameLabel.text = name; } } - (void)setColor:(NSString *)c { if(![c isEqualToString:color]) { color = [c copy]; UILabel *colorLabel = (UILabel *)[self.contentView viewWithTag:kColorValueTag]; colorLabel.text = color; } }
@synthesize會幫咱們自動建立get和set方法,但在這裏咱們須要本身寫set方法,所以經過上面的code來覆蓋系統自動爲咱們生成的set方法。2個set方法的實現是同樣的。首先比較新賦值的字符串和舊的字符串是否同樣,若是不同就進行賦值。而後須要解釋的就是這句話 UILabel *colorLabel = (UILabel *)[self.contentView viewWithTag:kColorValueTag]; 若是找到table view cell中的控件?即便使用剛纔咱們建立的2個常量,由於每個控件的tag值都是不同的,所以根據tag值就能夠很方便的找到咱們須要的控件,viewWithTag返回的類型是(UIView *),因此咱們將類型強制轉換成(UILable *),就能夠獲得咱們須要的Label了,而後對Label進行賦值。
5)添加BIDViewController代碼 打開BIDViewController.h,添加以下代碼
#import <UIKit/UIKit.h>
@interface BIDViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> @property (strong, nonatomic) NSArray *computers; @end
很簡單,不解釋。
打開BIDViewController.m,添加以下代碼
#import "BIDViewController.h" #import "BIDNameAndColorCell.h" @implementation BIDViewController @synthesize computers; ...... - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSDictionary *row1 = [[NSDictionary alloc] initWithObjectsAndKeys: @"MacBook", @"Name", @"White", @"Color", nil]; NSDictionary *row2 = [[NSDictionary alloc] initWithObjectsAndKeys: @"MacBook Pro", @"Name", @"Silver", @"Color", nil]; NSDictionary *row3 = [[NSDictionary alloc] initWithObjectsAndKeys: @"iMac", @"Name", @"Silver", @"Color", nil]; NSDictionary *row4 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Mac Mini", @"Name", @"Silver", @"Color", nil]; NSDictionary *row5 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Mac Pro", @"Name", @"Silver", @"Color", nil]; self.computers = [[NSArray alloc] initWithObjects:row1, row2, row3, row4, row5, nil]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; self.computers = nil; }
首先咱們引入BIDNameAndColor的頭文件,以後咱們將會建立它的實例,在viewDidLoad中,建立了5個NSDictionary,用於保存name和color名值對,使用的方法是initWithObjectsAndKeys,就是說下面的內容前一個做爲object,後一個做爲key,舉個例子,最後一個NSDictionary中,@"Mac Pro"就是object,@"Name"就是key。最後將5個NSDictionary保存到NSArray中(computers中)
在添加下面的code
#pragma mark - #pragma mark Table Data Source Methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.computers count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellTableIdentifier = @"CellTableIdentifier"; BIDNameAndColorCell *cell = [tableView dequeueReusableCellWithIdentifier:CellTableIdentifier]; if(cell == nil) { cell = [[BIDNameAndColorCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellTableIdentifier]; } NSUInteger row = [indexPath row]; NSDictionary *rowData = [self.computers objectAtIndex:row]; cell.name = [rowData objectForKey:@"Name"]; cell.color = [rowData objectForKey:@"Color"]; return cell; }
tableView:numberOfRowsInSection: 返回section中的行數 tableView:cellForRowAtIndexPath: 這個方法稍微有些不一樣,它吃建立了一個BIDNameAndColorCell的對象,而不是建立默認的UITableViewCell,這樣就能夠直接使用咱們本身定義的cell了,這裏雖然也指定了UITableViewCellStyleDefault,可是不會起做用,由於咱們本身定義了cell
以後的代碼應該很好理解,很直觀。
6)編譯運行
7)使用UITableViewCell控件,建立項目,添加table view,鏈接File's Owner 如今咱們使用第二種方法來定製UITableViewCell,最終的效果和上面的例子同樣,建立一個新的項目,一樣選擇Single View Application,命名爲Cells2
添加Table View,鏈接delegate和data source到File's Owner
8)添加BIDNameAndColorCell文件並編輯 和上面的例子同樣,添加BIDNameAndColorCell文件
打開BIDNameAndColorCell.h文件,添加以下代碼
#import <UIKit/UIKit.h>
@interface BIDNameAndColorCell : UITableViewCell <UITableViewDelegate, UITableViewDataSource>
@property (copy, nonatomic) NSString *name; @property (copy, nonatomic) NSString *color; @property (strong, nonatomic) IBOutlet UILabel *nameLabel; @property (strong, nonatomic) IBOutlet UILabel *colorLabel; @end
和以前有所不一樣的是,咱們多添加了2個Outlet,由於以後要添加xib,所以這2個outlet會指向xib上了2個UILabel
打開BIDNameAndColorCell.m文件,添加以下代碼
#import "BIDNameAndColorCell.h" @implementation BIDNameAndColorCell @synthesize name; @synthesize color; @synthesize nameLabel; @synthesize colorLabel; - (void)setName:(NSString *)n { if(![n isEqualToString:name]) { name = [n copy]; nameLabel.text = name; } } - (void)setColor:(NSString *)c { if(![c isEqualToString:color]) { color = [c copy]; colorLabel.text = color; } }
咱們從新定義了setName和setColor,這裏不須要使用tag,由於咱們直接使用outlet就能夠找到咱們須要的UILabel,另外咱們也沒在initWithStyle:reuseIdentifier中建立4個Label,由於咱們會在以後UITableViewCell控件中添加。
9)添加xib 在Project navigator中鼠標右鍵單擊Cells2文件夾,而後選擇New File...,在填出的對話框中左邊選擇User Interface,右邊選擇Empty,點擊Next
以後的Device Family中選擇iphone,點擊Next
命名爲BIDNameAndColorCell.xib,點擊Create
在Project navigator中選中BIDNameAndColorCell.xib文件,由於咱們建立的是Empy,所以GUI中什麼都沒有,在Object library中找到Table View Cell 拖到GUI中
選中view中的table view cell,打開Attributes inspector,找到Identifier,並設置爲CellTableIdentifier 這個Identifier就是以前咱們code中用到過的Identifier
10)向table view cell中添加控件 往table view cell中拖4個UILable
將左上方的UILabel命名爲"Name:",而後設置爲粗體(在attribute inspector中設置) 將左下方的UILabel命名爲"Color:",而後設置爲粗體(在attribute inspector中設置) 將右上方的UILabel拉到右邊出現輔助線的位置 將右下方的UILabel拉到右邊出現輔助線的位置 設置完成後的樣子以下 (沒必要將右邊2個Label的文字去掉,程序運行是會爲它們從新賦值)
11)關聯 接着咱們將BIDNameAndColorCell.xib和BIDNameAndColorCell文件關聯起來,選中GUI中的view,打開Identify inspector,將Class指定爲BIDNameAndColorCell
仍是選中view,切換到connections inspector,裏面有colorLabel和nameLabel 將colorLabel和nameLabel拖到view中對應的UILabel上,關聯起來(最右邊的2個label)
12)寫代碼 打開BIDViewController.h文件,添加以下代碼
#import <UIKit/UIKit.h>
@interface BIDViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> @property (strong, nonatomic) NSArray *computers; @end
這個和上一個例子同樣,不解釋了,打開BIDViewController.m文件,添加以下代碼
#import "BIDViewController.h" #import "BIDNameAndColorCell.h" @implementation BIDViewController @synthesize computers; ...... - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSDictionary *row1 = [[NSDictionary alloc] initWithObjectsAndKeys: @"MacBook Air", @"Name", @"Silver", @"Color", nil]; NSDictionary *row2 = [[NSDictionary alloc] initWithObjectsAndKeys: @"MacBook Pro", @"Name", @"Silver", @"Color", nil]; NSDictionary *row3 = [[NSDictionary alloc] initWithObjectsAndKeys: @"iMac", @"Name", @"Silver", @"Color", nil]; NSDictionary *row4 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Mac Mini", @"Name", @"Silver", @"Color", nil]; NSDictionary *row5 = [[NSDictionary alloc] initWithObjectsAndKeys: @"Mac Pro", @"Name", @"Silver", @"Color", nil]; self.computers = [[NSArray alloc] initWithObjects:row1, row2, row3, row4, row5, nil]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; self.computers = nil; } #pragma mark - #pragma mark Table View Data Source Methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.computers count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellTableIdentifier = @"CellTableIdentifier"; static BOOL nibsRegistered = NO; if(!nibsRegistered) { UINib *nib = [UINib nibWithNibName:@"BIDNameAndColorCell" bundle:nil]; [tableView registerNib:nib forCellReuseIdentifier:CellTableIdentifier]; nibsRegistered = YES; } BIDNameAndColorCell *cell = [tableView dequeueReusableCellWithIdentifier:CellTableIdentifier]; NSUInteger row = [indexPath row]; NSDictionary *rowData = [self.computers objectAtIndex:row]; cell.name = [rowData objectForKey:@"Name"]; cell.color = [rowData objectForKey:@"Color"]; return cell; }
咱們所要關心的就是tableView:cellForRowAtIndexPath這個方法中的if語句這段代碼:
if(!nibsRegistered) { UINib *nib = [UINib nibWithNibName:@"BIDNameAndColorCell" bundle:nil]; [tableView registerNib:nib forCellReuseIdentifier:CellTableIdentifier]; nibsRegistered = YES; }
UINib經過xib文件的名字找到xib文件,而後tableView會調用這個xib文件,nibsRegistered保證只有第一次調用這個方法的時候會去尋找並載入xib,以後則不會。
13)編譯運行 編譯運行程序,獲得的結果和以前的一個程序應該是同樣的
14)總結 這篇文章使用2種方式定製了UITableViewCell,一種是代碼實現,另外一種是傳統的拖控件實現,2種方法應該說各有利弊,不必定拖控件就是好的,我應該已經預感到之後的界面佈局應該都使用寫代碼來實現,已經有好幾個博友經過個人例子學習可是獲得的界面上面控件的佈局出現了差錯,目前的緣由是他們使用的模擬器和個人不同,我使用的是iPhone 5.0 Simulator,他們能夠是用其餘的模擬器,可是我以爲照成差錯的緣由是由於學習到如今咱們都是使用拖控件的方法來佈局的,這個會形成差錯,若是都是用code來實現佈局,那麼狀況應該會變得一致。
下一篇的內容會講到Table View的Section、index、搜索欄等等,內容比較多也比較實用,實現的效果以下 我會盡快寫完放上來的,謝謝你們的關注,有任何問題你們留言吧,若是我知道的話,我會盡可能回答,謝謝!