美文网首页
你真的读懂了UITableView吗

你真的读懂了UITableView吗

作者: Tomous | 来源:发表于2019-01-03 16:35 被阅读19次

相信对于学习iOS的童鞋,平时接触最多的,用到最多的就是UITableView了,那么你对UITableView了解多少呢?你真的会正确使用它吗?
下面就让我们一起走进UITableView的世界,去一点点的解析它,读懂它。

懒加载创建UITableView

-(UITableView *)tableView
{
    if (!_tableView) {
        _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height) style:UITableViewStyleGrouped];
        _tableView.separatorStyle = UITableViewCellStyleDefault;
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.backgroundColor = [UIColor whiteColor];
    }
    return _tableView;
}

separatorStylecell显示的样式

UITableViewCellStyleDefault,    // 左侧显示textLabel(不显示detailTextLabel),imageView可选(显示在最左边)
UITableViewCellStyleValue1,        // 左侧显示textLabel、右侧显示detailTextLabel(默认蓝色),imageView可选(显示在最左边)
UITableViewCellStyleValue2,        // 左侧依次显示textLabel(默认蓝色)和detailTextLabel,imageView可选(显示在最左边)
UITableViewCellStyleSubtitle    // 左上方显示textLabel,左下方显示detailTextLabel(默认灰色),imageView可选(显示在最左边)

styleUITableView的显示风格

UITableViewStylePlain,          //普通样式
UITableViewStyleGrouped        // 分组样式

UITableView的内部属性

设置表示图的行高(默认为44)
@property (nonatomic) CGFloat rowHeight

设置分组样式时的头视图高度和尾视图高度(当代理方法没有实现时才有效)
@property (nonatomic) CGFloat sectionHeaderHeight
@property (nonatomic) CGFloat sectionFooterHeight

设置一个行高的估计值(默认为0,表示没有估计,7.0之后可用),注意:这个属性官方的解释是如果你的tableView的行高是可变的,那么设计一个估计高度可以加快代码的运行效率。
下面这两个属性和上面相似,分别设置分区头视图和尾视图的估计高度(7.0之后可用)
@property (nonatomic) CGFloat estimatedRowHeight 
@property (nonatomic) CGFloat estimatedSectionHeaderHeight 
@property (nonatomic) CGFloat estimatedSectionFooterHeight 

设置分割线的位置
@property (nonatomic) UIEdgeInsets separatorInset

设置分割线的风格
@property (nonatomic) UITableViewCellSeparatorStyle separatorStyle
这个风格是一个枚举,如下:
typedef NS_ENUM(NSInteger, UITableViewCellSeparatorStyle) 
{   
  UITableViewCellSeparatorStyleNone,//无线    
  UITableViewCellSeparatorStyleSingleLine,//有线  
  UITableViewCellSeparatorStyleSingleLineEtched 
 };
设置分割线颜色
@property (nonatomic, strong, nullable) UIColor *separatorColor

设置分割线毛玻璃效果(IOS8之后可用) 
@property (nonatomic, copy, nullable) UIVisualEffect *separatorEffect

设置tableView头视图
@property (nonatomic, strong, nullable) UIView *tableHeaderView
设置tableView尾视图                        
@property (nonatomic, strong, nullable) UIView *tableFooterView

从复用池中取cell                      
- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier

获取一个已注册的cell
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath 

从复用池获取头视图或尾视图
- (nullable __kindof UITableViewHeaderFooterView *)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier 

通过xib文件注册cell
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier;

通过OC类注册cell
- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier 
上面两个方法是IOS6之后的方法。

通过xib文件和OC类获取注册头视图和尾视图
- (void)registerNib:(nullable UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier 
- (void)registerClass:(nullable Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier 

更改自定义分隔符值的解释方式。默认值是UITableViewSeparatorInsetFromCellEdges
@property (nonatomic) UITableViewSeparatorInsetReference separatorInsetReference
枚举类型
typedef NS_ENUM(NSInteger, UITableViewSeparatorInsetReference) {
    UITableViewSeparatorInsetFromCellEdges,//默认值,表示separatorInset是从cell的边缘的偏移量
    UITableViewSeparatorInsetFromAutomaticInsets//表示separatorInset属性值是从一个insets的偏移量
}

设置tableView背景view视图
@property (nonatomic, strong, nullable) UIView *backgroundView

获取section个数(只读属性)
@property (nonatomic, readonly) NSInteger numberOfSections;
设置每个section的行数
- (NSInteger)numberOfRowsInSection:(NSInteger)section;

获取分组的大小(包括头视图,所有行和尾视图)
- (CGRect)rectForSection:(NSInteger)section;    
 
根据分组分别获取头视图,尾视图和行的高度                               
- (CGRect)rectForHeaderInSection:(NSInteger)section;
- (CGRect)rectForFooterInSection:(NSInteger)section;
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;

获取某个点在tableView中的位置信息
- (nullable NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;    

获取某个cell在tableView中的位置信息                    
- (nullable NSIndexPath *)indexPathForCell:(UITableViewCell *)cell;                      

根据一个矩形范围返回一个信息数组,数组中是每一行row的位置信息
- (nullable NSArray<NSIndexPath *> *)indexPathsForRowsInRect:(CGRect)rect;       

通过位置路径获取cell                    
- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;   

获取所有可见的cell
@property (nonatomic, readonly) NSArray<__kindof UITableViewCell *> *visibleCells;

获取所有可见行的位置信息
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows;

根据分组获取头、尾视图
- (nullable UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section 
- (nullable UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section 

使表格示图定位到某一位置(行)
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
注意:indexPah参数是定位的位置,决定于分区和行号。animated参数决定是否有动画。scrollPosition参数决定定位的相对位置,它使一个枚举,如下:
typedef NS_ENUM(NSInteger, UITableViewScrollPosition)
 {    
  UITableViewScrollPositionNone,//同UITableViewScrollPositionTop   
  UITableViewScrollPositionTop,//定位完成后,将定位的行显示在tableView的顶部      
  UITableViewScrollPositionMiddle,//定位完成后,将定位的行显示在tableView的中间     
  UITableViewScrollPositionBottom//定位完成后,将定位的行显示在tableView最下面
};

使表格示图定位到选中行,这个函数与上面的非常相似,只是它是将表示图定位到选中的行。
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;

允许多个插入/删除/重新加载/移动 同时是动画。可嵌套的
- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates completion:(void (^ _Nullable)(BOOL finished))completion 

返回表视图是否包含删除占位符或重新排序它的行
@property (nonatomic, readonly) BOOL hasUncommittedUpdates


处理tableview在iPad上显示不全问题
@property (nonatomic) BOOL cellLayoutMarginsFollowReadableWidth 

设置tableview的contentView是否受到安全区域的限制
@property (nonatomic) BOOL insetsContentViewsToSafeArea 

设置是否自动将焦点分配到最后一个焦点索引路径上的项,默认为NO。如果YES,当聚焦一个表格视图,上一个索引路径自动聚焦。如果从来没有集中的表视图,那么首选集中使用索引路径
@property (nonatomic) BOOL remembersLastFocusedIndexPath 

设置TableView的是否开启拖放功能,dragInteractionEnabled 属性在 iPad 上默认是YES,在 iPhone 默认是 NO,只有设置为 YES 才可以进行 drag 操作
@property (nonatomic) BOOL dragInteractionEnabled 

获取指示是否从表视图中取消行,且尚未删除
@property (nonatomic, readonly) BOOL hasActiveDrag 

获取指示集合视图当前是否正在跟踪一个drop会话
@property (nonatomic, readonly) BOOL hasActiveDrop

UITableView 编辑模式

@property (nonatomic, getter=isEditing) BOOL editing;     
                        
默认状态是非编辑状态,如果不调用下面接口直接设置,是没有动画的
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;

当增减按钮按下时,用来处理数据和UI的回调。
8.0版本后加入的UITableViewRowAction不在这个回调的控制范围内,UITableViewRowAction有单独的回调Block。
 这个回调决定了在当前indexPath的Cell是否可以编辑。
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

左滑编辑cell的时候提交编辑
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.dataSource removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom];//删除刷新
    }else if (editingStyle == UITableViewCellEditingStyleInsert) {
        [self.dataSource insertObject:@"a" atIndex:indexPath.row];
        [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];//添加刷新
    }
    [self.tableView reloadData];
}

这个回调很关键,返回Cell的编辑样式,如果不设置,默认都是删除风格
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewCellEditingStyleInsert;
}
//UITableViewCellEditingStyle枚举类型
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
    UITableViewCellEditingStyleNone,
    UITableViewCellEditingStyleDelete,
    UITableViewCellEditingStyleInsert
};
//编辑样式枚举
UITableViewCellEditingStyleNone 没有编辑样式
UITableViewCellEditingStyleDelete 删除样式 (左边是红色减号)
UITableViewCellEditingStyleInsert 插入样式  (左边是绿色加号)
UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert 多选模式,左边是蓝色对号

自定义划动时delete按钮内容
- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
    return @"删除这行";
}

8.0后的新方法,侧滑菜单的新接口,支持多个侧滑按钮。用于自定义创建tableView被编辑时右边的按钮,按钮类型为UITableViewRowAction。
- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

这个接口决定编辑状态下的Cell是否需要缩进。
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;

滑动可以编辑时执行, 将要编辑和结束编辑时调用的方法
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"willBeginEditingRowAtIndexPath");
}
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath

iOS11 后的新方法,首先是可以给这些按钮添加图片了,然后是如果实现了以下两个新增的代理方法,将会取代(tableView: editActionsForRowAtIndexPath:)代理方法:
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIContextualAction *cancelAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"取消" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
        NSLog(@"取消");
        NSLog(@"%@", sourceView);
    }];
    UIContextualAction *ensureAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"删除" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
        NSLog(@"删除");
        NSLog(@"%@", sourceView);
    }];
    UISwipeActionsConfiguration *actions = [UISwipeActionsConfiguration configurationWithActions:@[cancelAction, ensureAction]];
    return actions;
}

-(UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
    //删除
    UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@"删除" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
        [self.dataSource removeObjectAtIndex:indexPath.row];
        completionHandler(YES);
        [self.tableView reloadData];
    }];
    deleteRowAction.image = [UIImage imageNamed:@"删除"];
    deleteRowAction.backgroundColor = [UIColor redColor];

    //添加
    UIContextualAction *insertRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"添加" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
        [self.dataSource insertObject:@"b" atIndex:indexPath.row+1];
        completionHandler(YES);
        [self.tableView reloadData];
    }];
    insertRowAction.backgroundColor = [UIColor cyanColor];
    
    UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction,insertRowAction]];
    return config;
}

这个回调决定了在当前indexPath的Cell是否可以移动
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

这个回调实现了以后,就会出现更换位置的按钮,回调本身用来处理更换位置后的数据交换
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    //先把要移动的数据保存
    id moveObj = [self.dataSource objectAtIndex:sourceIndexPath.row];
    //从数组中删除要移动的数据
    [self.dataSource removeObjectAtIndex:sourceIndexPath.row];
    //把要移动的数据插入到目标位置
    [self.dataSource insertObject:moveObj atIndex:destinationIndexPath.row];
}

移动特定的某行时执行
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
    NSLog(@"targetIndexPathForMoveFromRowAtIndexPath");
    //用于限制只在当前section下面才可以移动
    if(sourceIndexPath.section != proposedDestinationIndexPath.section){
        return sourceIndexPath;
    }
    return proposedDestinationIndexPath;
}         

设置cell是否可以被选中(默认为YES)
@property (nonatomic) BOOL allowsSelection 

设置cell编辑模式下是否可以被选中
@property (nonatomic) BOOL allowsSelectionDuringEditing;  

设置是否支持多选                               
@property (nonatomic) BOOL allowsMultipleSelection 

设置编辑模式下是否支持多选
@property (nonatomic) BOOL allowsMultipleSelectionDuringEditing

获取选中cell的位置信息
@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow; 

获取多选cell的位置信息
@property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForSelectedRows

代码手动选中与取消选中某行
- (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
注意:这两个方法将不会回调代理中的方法

数据与UI更新

开始标志
- (void)beginUpdates;  
结束标志
- (void)endUpdates;    

插入分区
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
animation参数是一个枚举,枚举的动画类型如下
typedef NS_ENUM(NSInteger, UITableViewRowAnimation)
 {    
  UITableViewRowAnimationFade,//淡入淡出   
  UITableViewRowAnimationRight,//从右滑入   
  UITableViewRowAnimationLeft,//从左滑入   
  UITableViewRowAnimationTop,//从上滑入  
  UITableViewRowAnimationBottom,//从下滑入   
  UITableViewRowAnimationNone,  //没有动画   
  UITableViewRowAnimationMiddle,          
  UITableViewRowAnimationAutomatic = 100  // 自动选择合适的动画
};
删除分区
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation

重载一个分区
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation 

移动一个分区
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection

插入一些行
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

删除一些行
- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

重载一些行
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation 

移动某行
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath 

示例
[tableView beginUpdates];   
[tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:1 inSection:0]] withRowAnimation:UITabl eViewRowAnimationLeft];   
 [dataArray removeObjectAtIndex:1];   
 [tableView endUpdates];
注意:不要在这个块中调用reloadData这个方法,它会使动画失效。

刷新tableView
- (void)reloadData

UITableView索引

设置索引栏最小显示行数
@property (nonatomic) NSInteger sectionIndexMinimumDisplayRowCount     
       
设置索引栏字体颜色                               
@property (nonatomic, strong, nullable) UIColor *sectionIndexColor 

设置索引栏背景颜色
@property (nonatomic, strong, nullable) UIColor *sectionIndexBackgroundColor

设置索引栏被选中时的颜色
@property (nonatomic, strong, nullable) UIColor *sectionIndexTrackingBackgroundColor

刷新索引栏,这个方法常用于新加或者删除了索引类别而无需刷新整个表视图的情况下
- (void)reloadSectionIndexTitles

右侧添加一个索引表
- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView

响应点击索引时的委托方法                             
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
dataSource数据源方法
返回多少组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

每组返回多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

每行返回的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

返回每组的头部标题title
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;   

返回每组的尾部标题title
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
delegate代理方法
返回每行,表头,表尾的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

设置行高,头视图高度和尾视图高度的估计值(对于高度可变的情况下,提高效率)
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section 
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section 

cell、 headerView、 footerView将显示的时候调用,预加载cell、headerView、footerView
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section

cell、 headerView、 footerView已经显示的时候调用
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath 
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section

设置自定义头视图和尾视图
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

设置辅助视图风格
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath

cell右边按钮格式为UITableViewCellAccessoryDetailDisclosureButton时,点击按扭时调用的方法
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"当前点击的详情button \n indexpath=%@",indexPath);
}

设置cell是否可以高亮
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath 

cell高亮和取消高亮时分别调用的函数
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath 
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath 

选中之前执行,判断选中的行(阻止选中第一行)
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
    if (row == 0)
        return nil;
    return indexPath;

}
将取消选中时执行, 也就是上次先中的行
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"上次选中的行是  \n indexpath=%@",indexPath);
    return indexPath;
}

已经选中和已经取消选中后调用的函数
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 
 
我们可能有需求需要长按某个控件来复制内容,直接使用下面的方法来调用系统的复制剪切那个功能。
-(BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0 && indexPath.row !=0) {
        return YES;
    }
    return NO;
}
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender  {
        if (action == @selector(copy:)) {
           return YES;
        }
        return NO;
}
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender {
        if (action == @selector(copy:))  {
            UsermessageCell *messageCell = (UsermessageCell *) 
            [tableView cellForRowAtIndexPath:indexPath];
            [UIPasteboard generalPasteboard].string = messageCell.messageLab.text;
        }
}

调用让你调整tableview中的行的弹簧加载行为
允许选择某一行的弹簧加载。 如果你想在弹簧加载的单元格的不同子视图上的交互效果,修改context.targetView属性。 默认
是单元格cell。 如果此方法未实现,则默认值为YES,除非该行是拖动会话drag session的一部分。
- (BOOL)tableView:(UITableView *)tableView shouldSpringLoadRowAtIndexPath:(NSIndexPath *)indexPath withContext:(id<UISpringLoadedInteractionContext>)context 

iOS9.0 新特征———焦点
使用Apple TV遥控器控制屏幕上的用户界面

 返回能否获得焦点
- (BOOL)tableView:(UITableView *)tableView canFocusRowAtIndexPath:(NSIndexPath *)indexPath 
返回是否将要更新焦点
- (BOOL)tableView:(UITableView *)tableView shouldUpdateFocusInContext:(UITableViewFocusUpdateContext *)context 
已经更新焦点时调用
- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator 
返回上一个焦点的indexPath
- (nullable NSIndexPath *)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView 

cell的缩进级别,动态静态cell必须重写,否则会造成崩溃iOS tableview静态cell动态cell混用

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath; 

UITableViewDataSourcePrefetching声明UITableView的滑动协议

@property (nonatomic, weak, nullable) id <UITableViewDataSourcePrefetching> prefetchDataSource

设置预读取的优先排序数组
- (void)tableView:(UITableView *)tableView prefetchRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;

取消提前加载数据 
- (void)tableView:(UITableView *)tableView cancelPrefetchingForRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;

UITableViewDragDelegate声明UITableView的拖拽协议

@property (nonatomic, weak, nullable) id <UITableViewDragDelegate> dragDelegate

提供一个 给定 indexPath 的可进行 drag 操作的 item(类似 hitTest: 方法周到该响应的view )如果返回 nil,则不会发生任何拖拽事件
- (NSArray<UIDragItem *> *)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath;

当接收到添加item响应时,会调用该方法向已经存在的drag会话中添加item
- (NSArray<UIDragItem *> *)tableView:(UITableView *)tableView itemsForAddingToDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point;

备注:1、当接收到添加item响应时,会调用该方法向已经存在的drag会话中添加item
2、如果需要,可以使用提供的点(在集合视图的坐标空间中)进行其他命中测试。
3、如果该方法未实现,或返回空数组,则不会将任何 item 添加到拖动,手势也会正常的响应

3、允许对从取消或返回到 CollectionView 的 item 使用自定义预览,如果该方法没有实现或者返回nil,那么整个 cell 将用于预览
- (nullable UIDragPreviewParameters *)tableView:(UITableView *)tableView dragPreviewParametersForRowAtIndexPath:(NSIndexPath *)indexPath;

开始拖拽之前会调用该方法(与dragSessionDidEnd一起使用)
- (void)tableView:(UITableView *)tableView dragSessionWillBegin:(id<UIDragSession>)session;

拖拽结束的时候会调用该方法
- (void)tableView:(UITableView *)tableView dragSessionDidEnd:(id<UIDragSession>)session;

控制拖动会话是否允许移动操作(默认是yes)
- (BOOL)tableView:(UITableView *)tableView dragSessionAllowsMoveOperation:(id<UIDragSession>)session;

控制拖动会话是否仅限于源应用程序(默认是no)
- (BOOL)tableView:(UITableView *)tableView dragSessionIsRestrictedToDraggingApplication:(id<UIDragSession>)session;

UITableViewDropDelegate声明UITableView的drop协议

@property (nonatomic, weak, nullable) id <UITableViewDropDelegate> dropDelegate

使用 dropCoordinator 去置顶如果处理当前 drop 会话的item 到指定的最终位置, 同时也会根据drop item返回的数据更新数据源(把TableView的拖放功能给打开)
- (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id<UITableViewDropCoordinator>)coordinator;

判断对应的item 能否被 执行drop会话
- (BOOL)tableView:(UITableView *)tableView canHandleDropSession:(id<UIDropSession>)session;

当drop会话进入到 tableView 的坐标区域内就会调用
- (void)tableView:(UITableView *)tableView dropSessionDidEnter:(id<UIDropSession>)session;

提供释放方案的方法
- (UITableViewDropProposal *)tableView:(UITableView *)tableView dropSessionDidUpdate:(id<UIDropSession>)session withDestinationIndexPath:(nullable NSIndexPath *)destinationIndexPath;

当 dropSession 不在tableView 目标区域的时候会被调用
- (void)tableView:(UITableView *)tableView dropSessionDidExit:(id<UIDropSession>)session;

当dropSession 完成时会被调用(适合在这个方法里做一些清理的操作)
- (void)tableView:(UITableView *)tableView dropSessionDidEnd:(id<UIDropSession>)session;

当 item 执行drop 操作的时候,可以自定义预览图,如果没有实现该方法或者返回nil,整个cell将会被用于预览图
- (nullable UIDragPreviewParameters *)tableView:(UITableView *)tableView dropPreviewParametersForRowAtIndexPath:(NSIndexPath *)indexPath;

相关文章

  • 你真的读懂了UITableView吗

    相信对于学习iOS的童鞋,平时接触最多的,用到最多的就是UITableView了,那么你对UITableView了...

  • 知识点不会融合怎么办?

    说到知识点,人人都会说:我学了呀,会了呀,一问到:懂了吗?懂了。真的懂了吗?真的懂了呀。确定吗?确定啊。那你把这个...

  • 如何阅读?20170213

    你真的会阅读吗?你读过的书真的读懂了吗?你理解了作者想要表达的概念、故事、逻辑了?你真的会选书吗?什么样的书才适合...

  • 如何让更多的人升级自己的操作系统,实现财富自由

    很多人都在说,我懂了那么多道理,为什么依然过不好这一生?其实你是真的懂了那些道理吗?即便是懂了那些道理,你有运用这...

  • 一本书,你不必懂它的全部。

    读一本书,你其实不必懂它的全部。 你读懂了多少,你就输出多少,哪怕只有一个点。 但你必须确定,你真的懂了! 那才不...

  • 赖佩霞 | 我是个什么样的观众?

    听别人说话,你真的听懂了他的意思吗? 说话时,你又真的了解自己正在做什么吗? 甲:他真的很讨人厌,每次都那样,他就...

  • 你真的读懂了论语吗?

    -序- 儒学虽然历经许多波折,但是依然穿过了两千年的历史迷雾,流传到了今天。 《论语》作为儒家经典,我们从小就耳濡...

  • 你真的读懂了空虚吗

    懒惰 人总是会把一些困难的(非必需的)事情一拖再拖,最后真的就没必要(不可能)完成,这种懒惰的性情会像个毒品毒害我...

  • 你真的弄懂了婚姻吗?

    一提及帮男人养家,我们脑海里浮现的必定是一个女强人的角色,在电视剧《完美关系》中,斯黛拉是公关界的女魔头,是个事业...

  • 懂或不懂,难得糊涂

    懂了,你就真的看透了吗? 不懂,你就真的会快乐吗? 懂或不懂,你还是你,你要做的就就是,让复杂的东西简...

网友评论

      本文标题:你真的读懂了UITableView吗

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