UITableVIewUIiOS

D12:UITableView(多行删除_UISearchBar

2015-05-19  本文已影响827人  Vinc

Inheritance

NSObject
UIResponder
UIView
UIScrollView
UITableView

一、UITableView多行删除

  1. NSArray(NSMutableArray)的2个实用方法
  2. 选中某一行后加入删除数据数组
  3. 点击NavigationBar右侧的Item执行的方法

二、UITableView结合搜索功能

  1. 搜索的控件
  2. 为搜索框添加数据源, 在UISearchResultsUpdating协议实现
  3. 判断是否在搜索,根据属性"isSearch"改写一些方法
  4. 发现问题, 去之前的地方修改
  5. 给表格添加右侧的索引(SectionIndex)

三、自定义UITableView每个Section的header,模拟QQ好友界面分组的点击展开收拢

  1. 当前选中的section, 初始值默认为0
  2. 在创建tableView的时候设置背景视图
  3. 显示表格的每个section的header
  4. 返回每一组有多少行
  5. �点击headView之后去判断点击的Section和之前已选中的Section的关系

一、UITableView多行删除

NSArray(NSMutableArray)的2个实用方法 :

- (void)removeObjectsInArray:(NSArray *)array

- (BOOL)containsObject:(id)anObject

  1. 将要删除的数据

    @property (nonatomic, strong) NSMutableArray *deleteArray;
    
  2. 为视图添加删除按钮

    // 点击进入表格多行选择的状态
    UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithTitle:@"删除" style:UIBarButtonItemStyleDone target:self action:@selector(beginDelete:)];
    self.navigationItem.rightBarButtonItem = rightItem;
    
    // 删除数据数组的初始化
    _deleteArray = [NSMutableArray array];        
  1. 默认是删除状态, 我们要修改为可以多选的编辑状态

    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
    

{
return UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert;
}
```

  1. 选中某一行后加入删除数据数组

    判断是否是在编辑模式下的点击: 没有判断的话, 在非多选状态下选中一条cell, 进入再退出编辑状态就会产生bug删除之前选中过的cell
    判断是否已经加入过删除数据数组

    • (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
      {
      if (tableView.editing == YES) { // 如果没有这句判断的话, 在非多选状态下选中一条cell, 进入再退出编辑状态就会产生bug删除之前选中过的cell
      // 获取选择的对象
      StudentModel *model = self.dataArray[indexPath.row];
      if (![self.deleteArray containsObject:model]) {
      // 添加到删除数据数组
      [self.deleteArray addObject:model];
      }
      }
      }

    // 取消选择, 表示不需要删除该数据

    • (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
      {
      // 获取取消选择的对象
      StudentModel *model = self.dataArray[indexPath.row];

      if ([self.deleteArray containsObject:model]) {
      [self.deleteArray removeObject:model];
      }
      }

  2. 点击NavigationBar右侧的Item执行的方法

    - (void)beginDelete:(id)sender
    {
        // 获取导航按钮上的文字
        NSString *title = self.navigationItem.rightBarButtonItem.title;
        **if ([title isEqualToString:@"删除"])** {
            // 进入表格的多选状态
            [self.tbView setEditing:YES animated:YES];
            // 将导航按钮文字改为"确定"
            self.navigationItem.rightBarButtonItem.title = @"确定";
        } **else { // 文字为"确定"**
            // 执行删除操作
            // 从数据源数组中删除需要删除的数据
            [self.dataArray removeObjectsInArray:self.deleteArray];
            
            // 取消表格的编辑状态
            [self.tbView setEditing:NO];
    
            // 刷新表格
            [self.tbView reloadData];
            
            // 将导航文字恢复成"删除"
            self.navigationItem.rightBarButtonItem.title = @"删除";
        }
    }
    

二、UITableView结合搜索功能

// 创建搜索视图
// iOS7: UISearchDisplayController 已不建议使用
// iOS8: UISearchController

  1. 搜索的控件

@property (nonatomic, strong) UISearchController *searchCtrl;


    * #### 创建搜索控件
    
    ```  
     - (void)createSearch
    {
        // 1. 存nil表示当前搜索结果就保存在当前视图控制器中, 而非是其他视图控制器
        _searchCtrl = [[UISearchController alloc] initWithSearchResultsController:nil];
        // 2. 设置代理
        _searchCtrl.delegate = self;
        // 3. 设置搜索数据更新的代理:怎样显示搜索结果
        _searchCtrl.searchResultsUpdater = self;
        
        // 4. 显示搜索条
        [_searchCtrl.searchBar sizeToFit];
        
        // 5. 添加到父视图
        /*
         tableHeaderView: 表格的表头, 显示在整个表格的上面
         tableFooterView: 表格的表尾, 显示在整个表格的下面
         */
        _tbView.tableHeaderView = _searchCtrl.searchBar;
        
        // 这样实现, 搜索结果也是显示到_tbView中
        // _tbView显示的数据, 就要区分是在搜索时, 还是非搜索的时候
}

// 存储符合搜索条件的数据
@property (nonatomic, strong) NSMutableArray *searchResultArray;

* #### 在搜索框里面的文字修改时调用
* #### 在这个方法里面实现搜索的功能
  
```
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
    // 如果搜索结果数组没有初始化, 初始化数组对象
    if (self.searchResultArray == nil) {
        _searchResultArray = [NSMutableArray array];
    }
    
    // 实现搜索的功能
    // 获取搜索的关键字
    NSString *keyword = self.searchCtrl.searchBar.text;
    
    // 从_dataArray数组里面找符合条件的数据
    for (NSArray *sectionArray in self.dataArray) {
        // 遍历每一个section里面的内容
        for (NSString *title in sectionArray) {
            // NSCaseInsensitiveSearch表示大小写不敏感: a与A,a都可以匹配
            NSRange range = [title rangeOfString:keyword options:NSCaseInsensitiveSearch];
            if (range.location != NSNotFound) {
                // 符合条件, 添加到搜索结果数组中
                [self.searchResultArray addObject:title];
            }
        }
    }
    // 显示数据
    [self.tbView reloadData];
}
```    

@property (nonatomic, assign) BOOL isSearch;
* 首先根据当前搜索状态给"isSearch"赋值

        // 进入搜索状态
   - (void)willPresentSearchController:(UISearchController *)searchController
   {
       self.isSearch = 1;
       [self.tbView reloadData];
   }
   
   // 退出搜索状态
   - (void)willDismissSearchController:(UISearchController *)searchController
   {
       // 结束搜索状态
       self.isSearch = 0;
       [self.tbView reloadData];
   }
* #### 根据属性"*isSearch*"改写一些方法    
   // 返回多少组
   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView  
   {
       **if (self.isSearch) {
           // 搜索时显示一组
           return 1;
       }**
       return self.dataArray.count;
   }
    ```    

   ```  
   // 返回每组多少行
   - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
   {
       **if (self.isSearch) {
           // 搜索时返回的行数
           return self.searchResultArray.count;
       }**
       return [self.dataArray[section] count];
   }
   ```
   ```
   // 返回cell
   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
   {
       **if (self.isSearch) {
           // 搜索时
           static NSString *SearchCellID = @"Search";
           UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SearchCellID];
           if (nil == cell) {
               cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SearchCellID];
           }
           // 显示数据
           cell.textLabel.text = self.searchResultArray[indexPath.row];
           return cell;
       }**
           原代码
   }
   ```  
   ```  
   // 每个Section的标题
   - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
   {
       if (self.isSearch) {
           return @"搜索结果";
       }
       return [NSString stringWithFormat:@"第%c组", (int)section+'A'];
   }  
   ```    
---
#### 发现问题, 去之前的地方修改
1. #### 修改UISearchController的属性
   
   1. 使搜索结果滑动: 隐藏前面的遮罩视图  
`    _searchCtrl.dimsBackgroundDuringPresentation = NO;`  
   2. 在搜索的时候显示导航栏  
   `_searchCtrl.hidesNavigationBarDuringPresentation = NO;`
 
2. #### 修改搜索词时重新刷新tableView    

// 在搜索框里面的文字修改时调用
// 在这个方法里面实现搜索的功能

  
 ---
* #### 给表格添加右侧的索引(*SectionIndex*)    
    1. **表格右侧索引的文字**
    
        ```
        //返回索引上面显示的文字内容
        //实现这个方法,系统或默认在右侧添加索引视图
        //点击相应地文字会跳转到对应的section
        //这种对应关系是按照顺序对应的
        //索引视图默认比较小,如果需要的话,可以自己去实现这个功能 
        
        /*
         自己实现功能的思路:
         添加一个视图,放在表格视图的右边
         在上面添加很多按钮
         点击按钮的事件中,设置表格视图的偏移量
         //计算位置
         //header的高度和cell的高度
         //_tbView scrollToRowAtIndexPath:<#(NSIndexPath *)#> atScrollPosition:<#(UITableViewScrollPosition)#> animated:<#(BOOL)#>
         */
         
        - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
        {
            NSMutableArray *array = [NSMutableArray array];
            //26个组对应的索引上面的标题分别是每个字母的大写
            for (int i='A'; i<='Z'; i++) {
                [array addObject:[NSString stringWithFormat:@"%c",i]];
            }
            return array;
        }
        
        ```
    2.  **实现另外一个代理方法,可以修改点击右边index项对应跳转的tableView的section顺序**
    
        ```
        - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
        {
            //参数中的index是索引数组里面的序号
            //返回的值是表格视图的section的序号
            return index;
        }  
        ```

  
* #### 为搜索框在右侧的*"sectionIndexTitles"*增加一个索引    

  

---
## 三、自定义UITableView每个Section的header,模拟QQ好友界面分组的点击展开收拢
* #### 当前选中的section, 初始值默认为0
`@property (nonatomic, assign) NSInteger selectSection;`

* #### 在创建tableView的时候设置背景视图 

UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"gamebg"]];
bgImageView.frame = _tbView.bounds;
_tbView.backgroundView = bgImageView;


* #### 显示表格的每个section的header      

    ```
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {
        // section的header的背景视图
        UIImageView *headerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
        headerImageView.image = [UIImage imageNamed:@"header"];
        
        // 创建标签, 显示在第几组
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(80, 0, 120, 40)];
        label.text = [NSString stringWithFormat:@"第%ld组", section + 1];
        [headerImageView addSubview:label];
    
        // 添加一个图片, 显示展开的状态
        UIImageView *leftImageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 0, 40, 40)];
        if (section == self.selectSection) {
            // 选中的图片
            leftImageView.image = [UIImage imageNamed:@"list_ico_d"];
        } else {
            // 未选中的图片
            leftImageView.image = [UIImage imageNamed:@"list_ico"];
        }
        [headerImageView addSubview:leftImageView];
        
        // 点击的功能
        // 添加一个手势
        // 打开用户交互
        UITapGestureRecognizer *g = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
        [headerImageView addGestureRecognizer:g];
        headerImageView.userInteractionEnabled = YES;
        headerImageView.tag = 200+section;
        
        return headerImageView;
    }  
    ```

* #### 返回每一组有多少行  
  
    ```  
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        if (section == _selectSection) {
            //选中的组里面的内容全部显示
            NSArray *sectionArray = _dataArray[section];
            return sectionArray.count;
        }else{
            //没有选中的组cell全部不显示,只显示header
            return 0;
        }
    }
    ```  
* #### 点击headView之后去判断点击的Section和之前已选中的Section的关系

    ```
    - (void)tapAction:(UIGestureRecognizer *)g
    {
        //获取点击的section
        UIImageView *headerView = (UIImageView *) g.view;
        NSInteger section = headerView.tag-200;
        NSLog(@"section:%ld",section);
        
        //赋值给选中section的成员变量
        if (section == _selectSection) {
            //点击的是已经展开的组
            //将展开的组关闭
            _selectSection = -1;
            [_tbView reloadData];
        }else{
            
            //点击的是关闭的组
            //将已经展开的组合并,将点击的组展开
            _selectSection = section;
            
            [_tbView reloadData];
        }
        
    }
    ```
上一篇下一篇

猜你喜欢

热点阅读