iOS TableView 編程指導(dǎo)(三)-創(chuàng)建和配置TableView

在展示TableView前要配置好, 設(shè)置TableView的delegate和DataSource對(duì)象.
本章用到的代碼來(lái)之demo:UITableView Fundamentals for iOSTheElements

創(chuàng)建TableView的基本知識(shí)


為創(chuàng)建TableView, 需要?jiǎng)?chuàng)建幾個(gè)相互交互的實(shí)體對(duì)象:視圖控制器, TableView自己和tableView的DataSource和delegate對(duì)象, 視圖控制器, DataSource和delegate通常是同一個(gè)對(duì)象. 視圖控制器的啟動(dòng)了調(diào)用序列, 圖3-1使用展示了這一過(guò)程.

  1. 視圖控制器使用frame和style來(lái)創(chuàng)建tableView實(shí)例. frame通常為screen的frame,減去各種bar(導(dǎo)航/狀態(tài)欄等)的高度即可. 在此刻也可設(shè)置一個(gè)全局變量表保存tableView, 或者用一個(gè)屬性保存tableView的全局屬性, 比如, 行高, autoresizing行為.
  2. 視圖控制器給tableView設(shè)置DataSource和delegate, 然后給TableView發(fā)送reloadData消息.
  3. TableView會(huì)給DataSource發(fā)送numberOfSectionsInTableView:消息, DataSource會(huì)使用該方法返回TableView的section數(shù), 這個(gè)方法時(shí)可選的, 但如果你的tableView中有多個(gè)section的話, 必須實(shí)現(xiàn)該方法來(lái)告知TableView具有多個(gè)section.
  4. 對(duì)于每一個(gè)section, DataSource都會(huì)收到TableView發(fā)送來(lái)的TableView:numberOfRowsInSection:消息, 該方法中返回每個(gè)section中的行數(shù)
  5. 之后DataSource會(huì)收到對(duì)應(yīng)的可見(jiàn)cell的tableView:cellForRowAtIndexPath:消息, 然后返回對(duì)應(yīng)cell的UITableViewCell對(duì)象, tableView使用該對(duì)象去繪制表視圖中的行.
圖3-1 創(chuàng)建和配置TableView調(diào)用時(shí)序圖

圖4-1展示了DataSource中的required方法加上numberOfSectionsInTableView:. DataSource和delegate除了實(shí)現(xiàn)required方法外, 可以實(shí)現(xiàn)其他optional方法來(lái)提供一些額外的特性, 比如實(shí)現(xiàn)tableView:titleForHeaderInSection:方法來(lái)給section提供title. 你可以創(chuàng)建plain或者grouped樣式的tableView, 盡管以兩種樣式創(chuàng)建表視圖的過(guò)程是相同的, 但是您可能希望執(zhí)行不同類型的配置. 例如, 因?yàn)榉纸M表視圖通常呈現(xiàn)項(xiàng)目細(xì)節(jié), 所以您可能還希望添加自定義附件視圖(例如, 開(kāi)關(guān)和滑塊)或自定義內(nèi)容(例如, 文本字段). 具體見(jiàn)詳細(xì)地看看tableView中的cell

創(chuàng)建和配置TableView的一些建議


在APP中, tableView的用法很多, 想怎么用就怎么用, 你可以自定義一個(gè)對(duì)象去創(chuàng)建, 管理, 配置tableView, 但是你應(yīng)該使用UIKit提供的設(shè)計(jì)好的一些關(guān)于tableView的類和技術(shù), 也應(yīng)該遵循UIKit對(duì)于tableView使用的一些規(guī)范, 比如數(shù)據(jù)/表現(xiàn)分離, 下面是UIKit關(guān)于創(chuàng)建和使用tableView的一些建議:

  • 盡量使用UITableViewController來(lái)創(chuàng)建和管理TableView
  • 如果你的APP中大量使用TableView的話, 那么你在創(chuàng)建xcode工程時(shí), 應(yīng)該使用Master-Detail應(yīng)用程序模板
  • 對(duì)于展示連續(xù)的TableView, 你應(yīng)該使用自定義的UITableViewController, 這樣你既可以從storyboard中加載TableView, 也可以通過(guò)代碼創(chuàng)建一個(gè)關(guān)聯(lián)TableView.

如果你的界面是多個(gè)視圖組合而成, 而TableView只是組成界面的一部分, 那么你應(yīng)該使用UIViewController來(lái)管理tableView, 不能用UITableViewController, 因?yàn)楹笳邥?huì)使得tableView的size固定填充屏幕(減去各種bar的空間).

使用storyboard來(lái)創(chuàng)建TableView


使用xcode創(chuàng)建包含tableView的APP時(shí), 選則模板應(yīng)該包含方便創(chuàng)建TableView的代碼存根和storyboard, 該模板提供一個(gè)骨架, 你只需添加而外的代碼和設(shè)置即可, 這樣很方便

創(chuàng)建基于TableView的APP:

  1. 選擇Xcode, 選擇文件>新建>項(xiàng)目
  2. 在彈出的對(duì)話框的左側(cè),選擇iOS, 選擇應(yīng)用程序
  3. 在對(duì)話框的中間主要區(qū)域中, 選擇'Mater-Detail 應(yīng)用程序', 點(diǎn)擊'下一步'
  4. 選擇項(xiàng)目選項(xiàng)(確保使用storyboard), 然后點(diǎn)擊'下一步'
  5. 選擇項(xiàng)目的保存位置, 然后點(diǎn)擊'創(chuàng)建'

在第四步選擇設(shè)備時(shí), 會(huì)決定項(xiàng)目中的storyboard數(shù)量. 點(diǎn)擊項(xiàng)目導(dǎo)航欄中的storyboard文件, 會(huì)顯示storyboard編輯視圖. 如果你選擇的是iPhone, 那么storyboard中包含一個(gè)TableViewController, 如圖3-2所示.


圖3-2 Master-Detail應(yīng)用中的master view controller對(duì)應(yīng)的storyboard

確保畫(huà)布上的場(chǎng)景表示代碼中的主視圖控制器

  • 在畫(huà)布上, 單擊場(chǎng)景標(biāo)題來(lái)選擇表視圖控制器
  • 單擊工具欄區(qū)域頂部的Identity button來(lái)打開(kāi)Identity inspector
  • 檢查工程中的類是否包含UITableViewController的子類

選擇TableView的Display Style

TableView風(fēng)格包括兩種:plain和grouped
在storyboard中選擇TableView的style

  1. 點(diǎn)擊scene的中間來(lái)選中tableView.
  2. 在工具欄中選擇Attributes inspector
  3. 在tableView的Attributes inspector中選擇plain或者grouped style

選擇TableView的Content Type

在設(shè)計(jì)tableView的內(nèi)容是, storyboard中有兩種便捷的方式.

  • Dynamic prototypes 設(shè)計(jì)的cell的prototype的目的是為了復(fù)用. 如果你的cell復(fù)用時(shí), 使用的是相同的layout, 那么使用Dynamic, Dynamic的內(nèi)容由表視圖數(shù)據(jù)源(表視圖控制器)在運(yùn)行時(shí)以任意數(shù)量的單元格進(jìn)行管理埂蕊。圖3-3顯示了帶有一個(gè)Dynamic的plain表視圖模闲。
    圖3-3 Dynamic tableView

注意:如果storyboard中的tableView是dynamic, 那么tableView一定需要一個(gè)DataSource對(duì)象, 也就是說(shuō)UITableViewController的子類需要實(shí)現(xiàn)data source協(xié)議

  • Static cells 使用是static cell的話, cell的內(nèi)容的layout, cell的個(gè)數(shù)已經(jīng)確定. TableView的cell和內(nèi)容在運(yùn)行前已經(jīng)確定好, 是固定的. 你還是設(shè)置section header等靜態(tài)信息. 當(dāng)TableView的cell的layout不會(huì)改變時(shí), 使用static cell. 如圖3-4, static cell的tableView.
圖3-4 static cell

注意:如果storyboard中的TableView使用static cell, 那么就不需要DataSource對(duì)象了, 因?yàn)門(mén)ableView的cell時(shí)確定的.

cell的重用標(biāo)識(shí)符(reuse identifier)是用來(lái)標(biāo)識(shí)重用的cell的, 標(biāo)識(shí)符的字符串最好是能夠描述cell中包含的內(nèi)容, 比如cell是用來(lái)展示鳥(niǎo)瞰圖的, 那么他的重用標(biāo)識(shí)符為@"BirdSightingCell"

設(shè)計(jì)TableView的cell

前面文章有講過(guò), UIKit為你提供了四種類型的cell. 如果系統(tǒng)提供的這四種類型不能滿足需求, 你可以繼承UITableViewCell來(lái)自定義cell. 具體如何自定義cell你將在接下來(lái)的文章學(xué)到, 請(qǐng)關(guān)注本系列文章.

TableViewCell可以擁有附加視圖(Accessory view). 附加視圖是UIKit提供顯示在cell的右邊的一個(gè)視圖, 比如disclosure indicator, 使用>圖標(biāo)來(lái)表示, 告訴用戶點(diǎn)擊該圖標(biāo)可以獲取更多信息.

創(chuàng)建多個(gè)TableView

如果你的APP中存在和管理著多個(gè)TableView, 那么往storyboard中多拖幾個(gè)TableView, 可以通過(guò)將你創(chuàng)建的UITableViewController子類和TableView綁定.
往工程中添加自定義類文件

  1. 打開(kāi)Xcode, 選擇File > New > File
  2. 在彈出的對(duì)話框中選擇iOS中的cocoa touch
  3. 在對(duì)話框中選擇Object-C類, 點(diǎn)擊下一步
  4. 輸入文件名稱, 選擇UITableViewController, 點(diǎn)擊下一步
  5. 選擇保存的路徑, 點(diǎn)擊創(chuàng)建

往storyboard中添加表視圖控制器

  1. 打開(kāi)要添加TableView的storyboard
  2. 在對(duì)象庫(kù)中拖一個(gè)TableViewController到storyboard中
  3. 選中添加的scene, 點(diǎn)擊utility area中的Identity button
  4. 在custom class組中, 選擇剛創(chuàng)建的類
  5. 選擇TableView的cell的style(dynamic/static)
  6. 往新的scene上添加一個(gè)segue

通過(guò)創(chuàng)建一個(gè)demo APP可以學(xué)到更多

通過(guò)Apple實(shí)戰(zhàn)指導(dǎo)Your Second iOS App: Storyboards, 你可以學(xué)習(xí)如何通過(guò)storyboard技術(shù)來(lái)創(chuàng)建APP, 在該指導(dǎo)文檔中, 你將會(huì)學(xué)習(xí)如何創(chuàng)建一個(gè)基于導(dǎo)航的APP, 以及如何創(chuàng)建使用TableView來(lái)構(gòu)建界面.

使用代碼創(chuàng)建tableView


使用UITableViewController的好處, 能夠省寫(xiě)很多代碼, 而且可以避免一些錯(cuò)誤.

實(shí)現(xiàn)DataSource和Delegate協(xié)議

使一個(gè)類成為T(mén)ableView的DataSource和delegate需要遵守UITableViewDatasSourceUITableViewDelegate協(xié)議. 代碼清單3-1展示TableView的DataSource和Delegate.

代碼清單3-1 遵守DataSource和delegate協(xié)議

@interface RootViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
 
@property (nonatomic, strong) NSArray *timeZoneNames;
@end

創(chuàng)建和配置tableView

第二步是alloc, init出TableView實(shí)例. 代碼清單3-2展示了創(chuàng)建一個(gè)plain表視圖, 然后設(shè)置各種屬性,frame, DataSource, delegate等信息, 在使用UITableViewController時(shí), 是不用設(shè)置這些屬性的, 因?yàn)樗詣?dòng)幫你設(shè)置好了
代碼清單3-2 創(chuàng)建一個(gè)tableView

- (void)loadView
{
    UITableView *tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
    tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
    tableView.delegate = self;
    tableView.dataSource = self;
    [tableView reloadData];
 
    self.view = tableView;
}

使用數(shù)據(jù)動(dòng)態(tài)填充tableView


當(dāng)TableView被創(chuàng)建后, TableView會(huì)收到reloadData消息, 讓TableView去訪問(wèn)DataSourcedelegate對(duì)象, 來(lái)獲取section, row等信息, 這時(shí)DataSource會(huì)告訴TableView該顯示多少section和row. 之后DataSource重復(fù)調(diào)用tableView:cellForRowAtIndexPath:方法,返回一個(gè)UITableViewCell對(duì)象, 來(lái)告訴tableView該如何繪制row.(當(dāng)你滾動(dòng)tableView時(shí), 也會(huì)導(dǎo)致tableView:cellForRowAtIndexPath:被調(diào)用, 這是因?yàn)樾耤ell會(huì)顯示).

前面提過(guò), 如果tableView是動(dòng)態(tài)的(dynamic), 那么就必須實(shí)現(xiàn)DataSource協(xié)議, 代碼清單3-3展示一個(gè)實(shí)現(xiàn)了DataSource和delegate協(xié)議的類.

代碼清單3-3 給動(dòng)態(tài)tableView填充數(shù)據(jù)

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [regions count];
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Number of rows is the number of time zones in the region for the specified section.
    Region *region = [regions objectAtIndex:section];
    return [region.timeZoneWrappers count];
}
 
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    // The header for the section is the region name -- get this from the region at the section index.
    Region *region = [regions objectAtIndex:section];
    return [region name];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *MyIdentifier = @"MyReuseIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier:MyIdentifier];
    }
    Region *region = [regions objectAtIndex:indexPath.section];
    TimeZoneWrapper *timeZoneWrapper = [region.timeZoneWrappers objectAtIndex:indexPath.row];
    cell.textLabel.text = timeZoneWrapper.localeName;
    return cell;
}

tableView:cellForRowAtIndexPath:方法中, 出于性能考慮, DataSource會(huì)盡可能的復(fù)用cell, 首先會(huì)發(fā)送一個(gè)dequeueReusableCellWithIdentifier:消息給到tableView, 要求TableView提供一個(gè)特定重用標(biāo)識(shí)符的復(fù)用cell, 如果該cell不存在, DataSource要負(fù)責(zé)創(chuàng)建該cell, 并設(shè)置特定的reuse identifier. DataSource還要負(fù)責(zé)設(shè)置cell的content(上例中, 設(shè)置text)然后返回cell給TableView. 具體如何設(shè)置cell的content請(qǐng)看后續(xù)文章詳細(xì)地看看tableView中的cell

如果你的cell是在storyboard定義的, 使用dequeueReusableCellWithIdentifier:方法進(jìn)行獲取cell時(shí)總是有效的, 如果那里不需要使用復(fù)用的cell, 那么該方法會(huì)返回一個(gè)使用storyboard信息創(chuàng)建的新cell. 這樣就不需要檢查返回值是否為nil了.

使用數(shù)據(jù)動(dòng)態(tài)填充tableView


如果TableView是靜態(tài)的, 那么就不需要DataSource對(duì)象了, TableView在編譯期配置了好, 不需要在運(yùn)行期在去調(diào)用DataSource的方法了. 但是你需要使用data model中的數(shù)據(jù)來(lái)填充TableView的內(nèi)容, 下面代碼清單3-4就是一個(gè)這樣的示例.(改代碼示例來(lái)源Your Second iOS App: Storyboards)
代碼清單3-4 使用數(shù)據(jù)填充靜態(tài)tableView

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    BirdSighting *theSighting = self.sighting;
    static NSDateFormatter *formatter = nil;
    if (formatter == nil) {
        formatter = [[NSDateFormatter alloc] init];
        [formatter setDateStyle:NSDateFormatterMediumStyle];
    }
    if (theSighting) {
        self.birdNameLabel.text = theSighting.name;
        self.locationLabel.text = theSighting.location;
        self.dateLabel.text = [formatter stringFromDate:(NSDate*)theSighting.date];
    }
}

上面的代碼實(shí)例中, 在viewDidLoad(該方法會(huì)等view加載到內(nèi)存后調(diào)用)對(duì)tableView進(jìn)行填充數(shù)據(jù), 其中一些屬性(birdNameLabel,locationLabel)是storyboard中的outlet.

填充索引列表


當(dāng)需要大量按字母分類排序的數(shù)據(jù)時(shí), 可以使用索引列表(如第一章圖1-2所示). 索引列表是一種plain風(fēng)格的TableView, 而且還需要對(duì)DataSource對(duì)象進(jìn)行一些特殊的設(shè)置:

  • sectionIndexTitlesForTableView:
    返回一組字符串作為index使用

  • tableView:titleForHeaderInSection:
    為每一個(gè)section指定一個(gè)index, 作為section的title

  • tableView:sectionForSectionIndexTitle:atIndex:
    指定用戶點(diǎn)擊進(jìn)入相應(yīng)的section的index.

在構(gòu)建索引列表時(shí), 用來(lái)填充tableView的數(shù)據(jù)結(jié)構(gòu)與索引結(jié)構(gòu)相符. 一般需要?jiǎng)?chuàng)建一個(gè)二維數(shù)組來(lái)保存數(shù)據(jù). section的個(gè)數(shù)通過(guò)外層數(shù)組來(lái)反映, 內(nèi)層數(shù)組代表一個(gè)section中的內(nèi)容, 而且還要對(duì)這些數(shù)組按照現(xiàn)行索引順序進(jìn)行排序(一般按照字面表排序, 如A-Z). 可以通過(guò)類UILocalizedIndexedCollation(該類可以根據(jù)特定localization)來(lái)對(duì)二維數(shù)組排序, 這樣可以簡(jiǎn)化構(gòu)建順序的二維數(shù)據(jù)這種數(shù)據(jù)結(jié)構(gòu).

模型對(duì)象需要提供一個(gè)string屬性和返回string的方法來(lái)供類UILocalizedIndexedCollation進(jìn)行檢驗(yàn). 如果模型對(duì)象提供的是一個(gè)方法, 那么這個(gè)方法應(yīng)該不需要參數(shù). 如果一個(gè)model對(duì)象可以代表tableView中的行, 這樣非常方便, 所以在定義model時(shí), 你可以定義一個(gè)屬性來(lái)保存section的index, 或者row的index. 代碼清單4-5展示了這樣的model的定義
代碼清單3-5 設(shè)計(jì)model類

@interface State : NSObject
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *capitol;
@property(nonatomic,copy) NSString *population;
@property NSInteger sectionNumber;
@end

在填充tableView數(shù)據(jù)之前, 你應(yīng)該將數(shù)據(jù)創(chuàng)建加載好. 下面代碼展示了數(shù)據(jù)的加載和數(shù)據(jù)的排序處理

代碼清單3-6 loading數(shù)據(jù)

- (void)viewDidLoad {
    [super viewDidLoad];
    UILocalizedIndexedCollation *theCollation = [UILocalizedIndexedCollation currentCollation];
    self.states = [NSMutableArray arrayWithCapacity:1];
 
    NSString *thePath = [[NSBundle mainBundle] pathForResource:@"States" ofType:@"plist"];
    NSArray *tempArray;
    NSMutableArray *statesTemp;
    if (thePath && (tempArray = [NSArray arrayWithContentsOfFile:thePath]) ) {
        statesTemp = [NSMutableArray arrayWithCapacity:1];
        for (NSDictionary *stateDict in tempArray) {
            State *aState = [[State alloc] init];
            aState.name = [stateDict objectForKey:@"Name"];
            aState.population = [stateDict objectForKey:@"Population"];
            aState.capitol = [stateDict objectForKey:@"Capitol"];
            [statesTemp addObject:aState];
        }
    } else  {
        return;
    }

當(dāng)數(shù)據(jù)加載完后, 可以使用UILocalizedIndexedCollation類對(duì)數(shù)據(jù)進(jìn)行處理

代碼清單3-7 對(duì)數(shù)據(jù)進(jìn)行索引化

// viewDidLoad continued...
    // (1)
    for (State *theState in statesTemp) {
        NSInteger sect = [theCollation sectionForObject:theState collationStringSelector:@selector(name)];
        theState.sectionNumber = sect;
    }
    // (2)
    NSInteger highSection = [[theCollation sectionTitles] count];
    NSMutableArray *sectionArrays = [NSMutableArray arrayWithCapacity:highSection];
    for (int i = 0; i < highSection; i++) {
        NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:1];
        [sectionArrays addObject:sectionArray];
    }
    // (3)
    for (State *theState in statesTemp) {
        [(NSMutableArray *)[sectionArrays objectAtIndex:theState.sectionNumber] addObject:theState];
    }
    // (4)
    for (NSMutableArray *sectionArray in sectionArrays) {
        NSArray *sortedSection = [theCollation sortedArrayFromArray:sectionArray
            collationStringSelector:@selector(name)];
        [self.states addObject:sortedSection];
    }
} // end of viewDidLoad

對(duì)上面代碼做一些說(shuō)明:

  1. 遍歷所有model數(shù)據(jù), 調(diào)用collation對(duì)象的sectionForObject:collationStringSelector:方法, 該方法的參數(shù)是一個(gè)model對(duì)象, 和一個(gè)model對(duì)象屬性或者定義的方法(用來(lái)進(jìn)行檢驗(yàn)的), 然后該方法會(huì)返回一個(gè)處于哪個(gè)section的index. 將前面的index設(shè)置為model的sectionNumber
  2. 創(chuàng)建一個(gè)section數(shù)組(外層), 保存每一個(gè)section中的數(shù)據(jù).
  3. 循環(huán)遍歷一個(gè)模型數(shù)組中的每個(gè)數(shù)據(jù), 將其加入相應(yīng)的section數(shù)組(內(nèi)存)中.
  4. 然后調(diào)用collation manager的sortedArrayFromArray:collationStringSelector:方法來(lái)對(duì)section數(shù)組(外層)中的內(nèi)層數(shù)組排序

經(jīng)過(guò)上面的步驟后, DataSource已經(jīng)將數(shù)據(jù)準(zhǔn)備好, 下面是具體設(shè)置列表的index, 代碼清單3-8展示了這一過(guò)程, 該過(guò)程調(diào)用了UILocalizedIndexedCollation類的兩個(gè)方法sectionIndexTitlessectionForSectionIndexTitleAtIndex:來(lái)完成任務(wù), 注意在方法tableView:titleForHeaderInSection:方法中, 會(huì)將空的section從列表中移除.

代碼清單3-8 為tableView提供section-index數(shù)據(jù)

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
 
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if ([[self.states objectAtIndex:section] count] > 0) {
        return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section];
    }
    return nil;
}
 
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
    return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}

最后實(shí)現(xiàn)DataSource協(xié)議方法, 如代碼清單3-9所示
代碼清單3-9 填充索引列表中的行

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.states count];
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[self.states objectAtIndex:section] count];
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"StateCell";
    UITableViewCell *cell;
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    State *stateObj = [[self.states objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    cell.textLabel.text = stateObj.name;
    return cell;
}

如果你的TableView是索引列表, 那么請(qǐng)注意, 你應(yīng)該將cell的accessoryType設(shè)置為UITableViewCellAccessoryNone.

經(jīng)過(guò)上面的一個(gè)步驟輪廓, 你可以調(diào)用reloadSectionIndextitles方法來(lái)reload列表的index

tableView的可選性配置


對(duì)于tableView, UIKit提供了很多Api來(lái)對(duì)tableView進(jìn)行配置, 可以在外觀和行為上對(duì)tableView進(jìn)行各種控制, 比如控制section, 控制row等等. 下面就這些配置提供幾個(gè)方向給你選擇.

添加一個(gè)自定義標(biāo)題

在對(duì)tableView進(jìn)行配置時(shí), 使用UITableView類的方法對(duì)tableView配置是全局性的. 下面代碼展示了如何為tableView添加一個(gè)自定義的title(使用UILabel)

代碼清單3-10 為tableView添加一個(gè)標(biāo)題

- (void)loadView {
    CGRect titleRect = CGRectMake(0, 0, 300, 40);
    UILabel *tableTitle = [[UILabel alloc] initWithFrame:titleRect];
    tableTitle.textColor = [UIColor blueColor];
    tableTitle.backgroundColor = [self.tableView backgroundColor];
    tableTitle.opaque = YES;
    tableTitle.font = [UIFont boldSystemFontOfSize:18];
    tableTitle.text = [curTrail objectForKey:@"Name"];
    self.tableView.tableHeaderView = tableTitle;
    [self.tableView reloadData];
}

提供一個(gè)section表示

代碼清單3-11 返回section的title

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    // Returns section title based on physical state: [solid, liquid, gas, artificial]
    return [[[PeriodicElements sharedPeriodicElements] elementPhysicalStatesArray] objectAtIndex:section];
}

縮進(jìn)一行

代碼清單3-12 設(shè)置行的縮進(jìn)

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
    if ( indexPath.section==TRAIL_MAP_SECTION && indexPath.row==0 ) {
        return 2;
    }
    return 1;
}

改變一行的高度

代碼清單3-13 控制不同行的行高

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat result;
    switch ([indexPath row])
    {
        case 0:
        {
            result = kUIRowHeight;
            break;
        }
        case 1:
        {
            result = kUIRowLabelHeight;
            break;
        }
    }
    return result;
}

自定義Cell

關(guān)于要自定義cell, 那么主要的操作集中在DataSource的tableView:cellForRowAtIndexPath:方法中, 返回一個(gè)自定義的UITableViewCell子類的cell, 具體內(nèi)容請(qǐng)看下篇文章詳細(xì)地看看tableView中的cell

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末藕筋,一起剝皮案震驚了整個(gè)濱河市芜茵,隨后出現(xiàn)的幾起案子占哟,更是在濱河造成了極大的恐慌扶关,老刑警劉巖章贞,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件页响,死亡現(xiàn)場(chǎng)離奇詭異啤握,居然都是意外死亡鸟缕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)排抬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)懂从,“玉大人,你說(shuō)我怎么就攤上這事蹲蒲》Γ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵届搁,是天一觀的道長(zhǎng)缘薛。 經(jīng)常有香客問(wèn)我窍育,道長(zhǎng),這世上最難降的妖魔是什么宴胧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任漱抓,我火速辦了婚禮,結(jié)果婚禮上恕齐,老公的妹妹穿的比我還像新娘辽旋。我一直安慰自己,他們只是感情好檐迟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布补胚。 她就那樣靜靜地躺著,像睡著了一般追迟。 火紅的嫁衣襯著肌膚如雪溶其。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天敦间,我揣著相機(jī)與錄音瓶逃,去河邊找鬼。 笑死廓块,一個(gè)胖子當(dāng)著我的面吹牛厢绝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播带猴,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼昔汉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拴清?” 一聲冷哼從身側(cè)響起靶病,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎口予,沒(méi)想到半個(gè)月后娄周,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沪停,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年酵使,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铃芦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疫向。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡煤蚌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窟哺,到底是詐尸還是另有隱情泻轰,我是刑警寧澤技肩,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布且轨,位于F島的核電站浮声,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏旋奢。R本人自食惡果不足惜泳挥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望至朗。 院中可真熱鬧屉符,春花似錦、人聲如沸锹引。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嫌变。三九已至吨艇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腾啥,已是汗流浹背东涡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倘待,地道東北人疮跑。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凸舵,于是被迫代替她去往敵國(guó)和親祖娘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1啊奄、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_x閱讀 15,968評(píng)論 3 119
  • 只說(shuō)點(diǎn)兒喜歡的贿条,好的…… 以功夫小子起家的實(shí)力派演員吳京,秉承著恩師吳彬師父的教誨——精增热、苦整以、巧三字訣歷練成長(zhǎng),如...
    Andy茶閱讀 268評(píng)論 0 0
  • build流程 構(gòu)建一次項(xiàng)目需要經(jīng)歷一些4個(gè)階段 預(yù)處理preprocess讀入頭文件,展開(kāi)宏 編譯生成匯編語(yǔ)言,...
    sea_biscute閱讀 1,547評(píng)論 0 6