美文网首页
GeekBand iOS应用开发实战学习笔记(第三周)

GeekBand iOS应用开发实战学习笔记(第三周)

作者: Hysoka | 来源:发表于2016-03-30 21:54 被阅读66次

    UITableView

    UITableView用来管理通用表格组件,通用表格组件需要考虑数据集的输入、每行数据的显示、行操作(包括点击、编辑、删除、插入、调整行顺序)。根据MVC编程的思想,UITableView只需要管理表格视图,和行操作,对数据的内部不需要干涉,由专门的数据来源提供。

    UITableVIew的结构

    TableVIew的数据来源是由UITableViewDataSource管理的,这是一个协议(protocal),只要遵守该协议的数据源都可以向UITableView提供数据。
    每个table view是由多个区块(section)组成的。
    上图中NSIndexPath指向的区域是一个section,每个section里都有section header和section footer。在中间是由行(row)组成的。
    当用户用手点击其中的某一行,将向UITableViewDelegate发送一个事件响应消息,UITableViewDelegate再做出对应的响应。

    代码实现

    在ViewController.h头文件中加入对UITableDataSource和UITableViewDelegate的协议支持。
    @interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
    UITableDataSource协议中有两个required方法:
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section \\\设置整个表格有几个区块 -(NSInteger)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath \\\设置表格中区块有几行
    可在ViewController.m文件中添加所需的UITableDataSource协议中方法。

    UITableView的style有plain、grouped两种属性
    .dataSource经常使用的的方法有:

    numberOfSectionsInTableView:
    tableView:numberOfRowsInSection:
    tableView:cellForRowAtIndexPath:
    tableView:viewForHeader/FooterInSection: 
    

    .delegate经常使用的方法有:

    tableView:didSelectRowAtIndexPath:
    

    UITableViewCell的使用
    重复使用与Cell Identifier

    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
    if (cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
    }
    return cell;
    

    系统为UITableViewCell提供了不同的风格,包括:Default, Value1,Value2 Subtitle
    如果想定制自己风格的表格有多种方法
    1、用StoryBoard prototype 提供cell:可以用view tag访问界面,也可以用子类里的outlet访问界面。
    2、用xib提供cell:可以用registerNib方法注册xib,也可以用registerClass的方法注册xib。

    上课演示代码的详解:
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if ( section == 0) { //设置第一个区块有3行,其他区块有10行
    return 3;
    }
    else {
    return 10;
    }

    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView * header = [[UIView alloc] init];  //创建了一个header
    header.backgroundColor = [UIColor redColor];  //设置header的背景色
    return header;
    
    
    - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    UIView * footer = [[UIView alloc] init];  //创建了一个footer
    footer.backgroundColor = [UIColor blueColor];  //设置footer的背景色
    return footer;
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    tableView.rowHeight = 128; // change it and watch number of cells alive.
    NSString * cellID = [NSString stringWithFormat:@"cell_sec_%ld", (long)indexPath.section ];
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if ( cell == nil ) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID]; // there are more built-in styles
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
    cell.textLabel.text = [NSString stringWithFormat:@"%ld", (long)indexPath.row];
    cell.detailTextLabel.text = [NSString stringWithFormat:@"section %ld - row %ld", (long)indexPath.section, (long)indexPath.row];
    if ( indexPath.section == 0 ) {
        cell.imageView.image = [UIImage imageNamed:@"gear"];
    } else {
        cell.imageView.image = [UIImage imageNamed:@"guitar"];
    }
    return cell;
    
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 3;
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self performSegueWithIdentifier:@"showDetail" sender:indexPath];
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    
    - (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
     - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ( [segue.identifier isEqualToString:@"showDetail"] ) {
        DetailedViewController * dvc = segue.destinationViewController;
        dvc.indexPath = sender;
    }
    

    UITableViewController
    可以用来管理UITableView,当UITableView嵌在UITableViewController里时可以使用static cell,支持下拉刷新界面。
    下拉刷新界面代码:

    self.refreshControl = [[UIRefreshControl alloc] init];
    self.refreshControl.attributedTitle = [[NSAttributeString alloc] initWithString:@"Scan"]; //这段代码需要放到viewDidappear里
    [self.refreshControl addTarget:self action:@selector(refreshing:)forControlEvents:UIControlEventValueChanged];
    

    响应代码

    - (IBAction)startRefresh:(id)sender{
      [self.refreshControl endRefreshing];
      [self.tableView reloadData];
    }
    

    当刷新表格时UITableView并不知道dataSource有变化,有一系列reload方法来让UITableView来更新变化。
    reloadData 用来刷新整个表格
    reloadRowsAtIndexPaths:withRowAnimation: 用来刷新行
    reloadSections:withRowAnimation: 用来刷新整个区块
    reloadSectionIndexTitles 用来刷新索引

    刷新页面的关键代码

    - (IBAction)startRefresh:(id)sender{
      self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:@"scanning"];
      [self performSelector:@selector(stopRefreshing) withObject:nil afterDelay:1.0]; //一秒钟以后停止刷新方法
    }
    
    - (void) stopRefreshing{
      [self.refreshControl endRefreshing];
      [self.tableView reloadData];
    }
    

    TableView的交互
    在TableView中选择某一行是最基本的操作。
    选中的响应

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath  //选中某一行
    -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath  //将某一行的状态改为未选中
    
    -(void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;  //用代码选中,scrollPosition有几种选项可选,UITableScrollPositionTop, UITableScrollPositionMiddle,UITableScrollPositionBottom,UITableScrollPositionNone
    -(void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
    
    NSIndexPath *indexPathForSelectedRow
    NSArray<NSIndexPath *> *indexPathsForSelectedRows
    

    控制表格滚动

    - scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
    -scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
    

    上面代码中的UITableViewScrollPosition参数有四种
    UITableScrollPositionTop 行出现在表顶
    UITableScrollPositionMiddle 行出现在表中间
    UITableScrollPositionBottom 行出现在表底
    UITableScrollPositionNone 就近

    编辑模式

    UITableView的编辑模式

    编辑模式的响应过程

    UITableView编辑模式的响应过程

    带索引的表格

    带索引的表格

    高亮与菜单

    高亮与菜单

    表格的搜索:在iOS8以后,表格的搜索可以用UISearchController。

    CollectionView

    有的界面用TableView实现起来不怎么方便(比如横向滚动、一行放多个项目),我们可以使用CollectionView。
    CollectionView是对UITableView的扩展,增加了网格式界面,对表格内部职责进一步细分,分离出了Layout类。

    CollectionView总体结构与TableView相近,但有一些变化,在TableViewcell中的cell在CollectionView中叫item。header/footer在CollectionView中统一叫supplementary view。item view必须register。布局交给独立的layout类edit方法不再指定动画类型。

    cell 供应

    关键代码
    创建 Collection View

    -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
        return 1;
    }
    
    -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return 13;
    }
    
    -(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
        ImageCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ImageCell" forIndexPath:indexPath];
        cell.imageView.image = [self imageOfCityWithId:indexPath.item];
        return cell;
    }
    

    提供 DataSource

    -(UIImage*)imageOfCityWithId:(NSInteger)cityId {
        return [UIImage imageNamed:[NSString stringWithFormat:@"city%d",(int)cityId]];
    }
    

    提供supplementary view的方式

    -(UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
        return [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"citiesHeader" forIndexPath:indexPath];
    }
    

    刷新数据
    reloadData
    reloadSections:(NSIndexSet *)
    reloadItemsAtIndexPaths:(NSArray<NSIndexPath >)

    将一组编辑或刷新动作合作到一个动画过程里
    -performBatchUpdates:completion:

    手工移动格子
    beginInteractiveMovementForItemAtIndexPath: //开始拖动制定的格子
    updateInteractiveMovementTargetPosition: //更新选定格子被拖到的位置
    endInteractiveMovement 或 cancelInteractiveMovement //结束

    CollectionView Delegate 里交互的相关方法

    Collection View Delegate

    相关文章

      网友评论

          本文标题:GeekBand iOS应用开发实战学习笔记(第三周)

          本文链接:https://www.haomeiwen.com/subject/emhjlttx.html