day12---UITableView

UITableView 表格視圖
一 UITableView
1.1是什么?
以列表的方式展示數據的一種控件,且繼承自UISrollView,默認是只能上下滾動;

1.2 使用步驟:
    1)創建UITableView對象,并設置樣式;
    2)配置要展示的數據和外觀;
        三問:
        1)有幾個分區?
        2)每個分區有多少行?
        3)每行的展示的內容是什么?
    3)把它添加到父視圖上顯示;
見【Demo】-【1-UITableView】
  • (void)viewDidLoad {
    [super viewDidLoad];

    self.automaticallyAdjustsScrollViewInsets = NO;(消除導航控制器對其的影響)

    /********** 創建UITableView ************/
    //UITableViewStylePlain 普通平板樣式
    //UITableViewStyleGrouped 分組樣式
    UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, screenBounds.size.width, screenBounds.size.height-64) style:UITableViewStylePlain];

    myTableView.delegate = self;
    myTableView.dataSource = self;

    [self.view addSubview:myTableView];
    }

pragma mark -UITableViewDataSource

//三問 【** 重點 **】
//1問,告訴tableView應該顯示多少個分區【如果不實現,默認是1個分區】

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{

    return 1;
    }

//2問,告訴tableView每個分區顯示多少行 (該方法有幾個分區調用幾次)

  • (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return [self.dataArray count];
    }

//3問,告訴tableView每一行顯示的具體內容是什么

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    //創建靜態的標識
    static NSString *cellID = @"MyCell";
    //先從tableView的復用池中去查找沒有帶cellID標識的單元格;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    //如果沒有找到(復用池中沒有符合條件的單元格)
    if (cell == nil) {
    //自己創建一個新的單元格,并初始化單元格的樣式,給它加上標識
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];

    }
    //什么是indexPath?indexPath.row?
    MyModel *model = self.dataArray[indexPath.row];
    cell.textLabel.text = model.title;

    //返回符合條件的單元格對象;
    return cell;
    }

1.3 cell簡介 【重點】
UITableView的每一行都是一個UITableViewCell類型的對象,通過dataSource的第三問來初始化每一行;

【cell 的復用機制】
當滾動列表時候,部分UITableViewCell會移出窗口;UITableView會將移出去的UITableViewCell放入到一個復用池中,等待重用,當UITableView要求返回UITableViewCell的時候,會先查看復用池,如果池中有未使用的病符合條件的UITableViewCell,就會直接拿來使用,并重新配置這個UITableViewCell展示的內容,然后返回給UITableView,如果池子中沒有符合條件的cell,那么則創建一個新的UITableViewCell對象,并返回!

cell的復用機制保證了值創建有限個cell的對象,來顯示無限條數據,極大限度的節約了內存的開銷,提高了性能,具有極大的借鑒意義;

1.4 UITableView的原理
a 先詢問有幾個分區

b 根據分區的個數,再多次詢問每個分區有多少行,每次詢問的時候,會攜帶分區的section;

c 根據分區號及分區內的行號,再多次詢問每一行顯示的內容是什么,其中分區號section和行號row會組成一個NSIndexPath的類型,作為參數傳遞給方法;
  • (void)viewDidLoad {
    [super viewDidLoad];

    //1.請求數據
    [self reloadData];
    //2.創建UITableView
    [self creatUITableView];
    }
    -(void)creatUITableView
    {
    self.automaticallyAdjustsScrollViewInsets = NO;

    //添加背景圖片
    UIImageView *bgImg = [[UIImageView alloc] initWithFrame:screenBounds];
    bgImg.image = [UIImage imageNamed:@"5.jpg"];
    // [self.view addSubview:bgImg];

    UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, screenBounds.size.width, screenBounds.size.height-64) style:UITableViewStyleGrouped];
    //必寫
    myTableView.delegate = self;
    myTableView.dataSource = self;
    // myTableView.backgroundColor = [UIColor clearColor];
    myTableView.backgroundView = bgImg;

    UIImageView *headerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
    headerView.image = [UIImage imageNamed:@"10.jpg"];
    headerView.contentMode = UIViewContentModeScaleAspectFit;
    UIImageView *footerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
    footerView.image = [UIImage imageNamed:@"15.jpg"];
    footerView.contentMode = UIViewContentModeScaleAspectFit;
    //給myTableView設置頭部視圖
    myTableView.tableHeaderView = headerView;
    //給myTableView設置尾部視圖
    myTableView.tableFooterView = footerView;

    [self.view addSubview:myTableView];
    }

pragma mark -UITableViewDataSource

//3問 每行顯示的內容是什么

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    static NSString *cellID = @"cellName";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if (cell == nil) {
    //系統給我們提供了3中Cell樣式
    // UITableViewCellStyleDefault,
    // UITableViewCellStyleValue1,
    // UITableViewCellStyleValue2,
    // UITableViewCellStyleSubtitle
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
    }
    //將數據源中的數據,賦值給cell對象展示出來
    UserModel *model = self.dataArray[indexPath.section][indexPath.row];
    //1.顯示主標題
    cell.textLabel.text = model.name;
    //2.設置頭像
    cell.imageView.image = [UIImage imageNamed:model.iconImage];

    //設置圓角
    cell.imageView.layer.cornerRadius = 8;
    cell.imageView.layer.masksToBounds = YES;
    // cell.imageView.layer.borderColor = (__bridge CGColorRef)([UIColor redColor]);
    // cell.imageView.layer.borderWidth = 10;

    //3.顯示副標題
    cell.detailTextLabel.text = model.detailTitle;

    //設置cell右側的提示樣式
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.backgroundColor = [UIColor clearColor];

    return cell;
    }

/**************************** 相關屬性 *******************************/
//設置分區cell的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}

//設置分區的頭部視圖的標題
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%c區的頭部標題",(char)('A'+section)];

}

//設置分區的尾部標題
-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%c區的尾部標題",(char)('A'+section)];
}

/****************** 自定義分區的頭部,尾部視圖 **********************/
//當同時設置分區的頭部標題和頭部視圖,那么優先顯示頭部視圖
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = [NSString stringWithFormat:@"%c區的頭部標題",(char)('A'+section)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:20];
label.backgroundColor = [UIColor cyanColor];
label.textColor = [UIColor redColor];
return label;
}

-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = [NSString stringWithFormat:@"%c區的尾部標題",(char)('A'+section)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:15];
label.backgroundColor = [UIColor magentaColor];
label.textColor = [UIColor yellowColor];
return label;
}

/********************* 設置分區的頭部視圖的高度 ****************/
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 100;
}

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 50;
}

//設置右邊索引
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableArray *mArr = [NSMutableArray array];
for (int i='A'; i<='Z'; i++) {
NSString *str = [NSString stringWithFormat:@"%c",i];
[mArr addObject:str];
}
return mArr;
}

1.5 UITableViewController 表格視圖控制器
UIViewController 管理視圖的
UINavigationController 管理多個UIViewController
UITabBarController 即可以管理導航控制器,也可以管理UIViewController

2.1 概念
UITableViewController管理的是一個UITableView;
為了配合UITableView的使用而專門設立的一種特殊控制器,專門用來管理表格視圖;

2.2 特點:
1)繼承自UIViewController

2)自帶的視圖已經是UITableView類型,通過 .tableView的屬性來訪問自己攜帶的表格視圖;

3)控制器本身已經默認遵守了UITableViewDelegate和UITableViewDataSource,并且設置了自己作為該表格式圖的代理對象;

4)創建一個表格式圖控制器類,繼承自UITableViewController,在這個類中專心處理相關代理方法【最主要的三問】;
見【Demo】-【3-UITableViewController】
  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    //從表格視圖的復用池中按照之前注冊指定的標識去取可重用的對象;
    //該方法一定會返回一個不為nil的對象;
    //因為:復用池中如果沒有可重用的單元格,系統會根據之前注冊的類,自動的創建一個單元格對象并返回;
    //如果復用池中有可重用的單元格,系統會直接返回;
    //優點:自動處理一切細節,減少代碼量;
    //缺點:這種形式返回的cell對象,只能是默認的樣式,其他的三種樣式無法設置;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];

    //取出數據源中對應的數據模型,并展示在cell上
    StudentModel *model = self.dataArray[indexPath.section][indexPath.row];
    cell.textLabel.text = model.name;
    cell.imageView.image = [UIImage imageNamed:model.icon];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return cell;
    }

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}

pragma mark -UITableViewDelegate

//一答 【** 重點 **】
//當選中cell的時候,調用該方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//拿到當前點擊的cell所對應的數據模型
StudentModel *model = self.dataArray[indexPath.section][indexPath.row];

//跳轉到詳情頁面
DeatilViewController *dvc = [[DeatilViewController alloc] initWithNibName:@"DeatilViewController" bundle:nil];
//把這個model屬性傳值給詳情頁面
dvc.model = model;
__block MyTableViewController *weakself = self;
dvc.block = ^{
    //刷新當前的tableView(系統自帶的方法)
    [weakself.tableView reloadData];
    
};
[self.navigationController pushViewController:dvc animated:YES];

}

關于單元格的實現方法:
方式一:
1)定義靜態標識
2)根據標識從復用池中取對象
3)如果有,重新賦值后,直接使用
4)如果沒有,那么新建一個單元格
方法二:
1)在viewDidLoad中,提前注冊號單元格,并指定標識
2)在第三問時,直接從復用池中取,就算沒有可重用的單元格,系統內部會根據一早注冊號的單元格樣式創建單元格,并返回,如果有可重用的,直接返回;
《但方法二生成的單元格樣式只能是默認樣式,其他樣式無法設置》

兩種設置cell顯示內容的方式: 【** 重點 **】

第一種:
  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    //創建靜態的標識
    static NSString *cellID = @"MyCell";
    //先從tableView的復用池中去查找沒有帶cellID標識的單元格;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    //如果沒有找到(復用池中沒有符合條件的單元格)
    if (cell == nil) {
    //自己創建一個新的單元格,并初始化單元格的樣式,給它加上標識
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];

    }
    //什么是indexPath?indexPath.row?
    MyModel *model = self.dataArray[indexPath.row];
    cell.textLabel.text = model.title;

    //返回符合條件的單元格對象;
    return cell;
    }

第二種:
//提前注冊cell

[cView registerClass:[MyCell class] forCellWithReuseIdentifier:@"Cell"];

//3問 每一項顯示什么內容
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//從復用池中取有沒有符合要求的單元格,如果有,直接返回使用,如果沒有,系統會根據之前注冊的單元格,自動的創建一個單元格對象,并返回;
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
//因為UICollectionViewCell是系統自帶的cell,所以沒有提供樣式,沒有提供對應的空間,只能設置相關屬性;
cell.model = self.dataArray[indexPath.section][indexPath.row];

cell.backgroundColor = [UIColor orangeColor];


return cell;

}

如果cell用xib寫的話,提前注冊用下面這種寫法:
[self.tableView registerNib:[UINib nibWithNibName:@"AppCell" bundle:nil] forCellReuseIdentifier:@"AppCellID"];

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    AppCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AppCellID" forIndexPath:indexPath];

    cell.model = self.dataArray[indexPath.row];

    return cell;
    }

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容