UITableView

一、简介

<<UITableView(或简单地说,表视图)的一个实例是用于显示和编辑分层列出的信息的一种手段

<<继承关系:UITableView-->UIScrollView-->UIView-->UIResponder-->NSObject

格式为

1-->获取UITableView的风格(作用)

typedef NS_ENUM(NSInteger, UITableViewStyle) {

    UITableViewStylePlain,          // regular table view

    UITableViewStyleGrouped        // preferences style table view

};(如果属性有枚举类型的话,这里会有枚举类型说明

DLog(@"%@",tableview.style);(这是具体的例子

@property (nonatomic, readonly) UITableViewStyle style;// 只读属性    (这是说明

二、UITableView的初始化方法(属性的顺序与苹果API一致)

1-->初始化UITableView

typedef NS_ENUM(NSInteger, UITableViewStyle) {

    UITableViewStylePlain,          //普通样式

    UITableViewStyleGrouped        //分组样式

};

 tableview = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, 4*44+20) style:UITableViewStylePlain];//初始化方法

- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER;//必须在创建时指定样式。-initWithFrame:用UITableViewStylePlain调用它。

2-->初始化UITableView

- (instancetype)initWithCoder:(NSCoder*)coder{

self= [superinitWithCoder:coder];

if(self) {

NSLog(@"%s %@",__func__,NSStringFromCGRect(self.frame));

 }

return self;

}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

三、UITableViewCell的属性

1-->获取UITableView的风格

typedef NS_ENUM(NSInteger, UITableViewStyle) {

    UITableViewStylePlain,          //普通样式

    UITableViewStyleGrouped        //分组样式

};

 DLog(@"%@",tableview.style);//输出UITableView的风格

@property (nonatomic, readonly) UITableViewStyle style;// 只读属性    

2、声明UITableView的数据源

 tableview.dataSource = self;

@property (nonatomic, weak, nullable) id<UITableViewDataSource> dataSource;

3、声明UITableView的代理

 tableview.delegate = self;

@property (nonatomic, weak, nullable) id<UITableViewDelegate> delegate;

4、声明UITableView的滑动协议

tableview.prefetchDataSource = self;

@property (nonatomic, weak, nullable) id <UITableViewDataSourcePrefetching>prefetchDataSource NS_AVAILABLE_IOS(10_0);

5、声明UITableView的拖拽协议

tableview.dragDelegate = self;

@property (nonatomic, weak, nullable) id<UITableViewDragDelegate> dragDelegate API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);

6、声明UITableView的drop协议

tableview.dropDelegate = self;

@property (nonatomic, weak, nullable) id<UITableViewDropDelegate> dropDelegate API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);

7、UITableView的行高

tableView.rowHeight =100;

@property (nonatomic) CGFloat rowHeight; // 默认是自动布局 (UITableViewAutomaticDimension)

8、UITableView的行高

tableView.rowHeight = UITableViewAutomaticDimension //和autolaayout配合使用,自适应cell的高度

tableView.estimatedRowHeight = 100;

第一句的作用如前面所述,是开启iOS 8的单元格的自适应高度特性。第二句代码也是同样的功能,estimatedRowHeight让你提供一个预先估计cell的高度值,这个值根本可以乱设(只要不为0),但如果你不写这句,或者将estimatedRowHeight属性设置为0,则iOS 8的单元格自动高度特性也不会生效

@property (nonatomic) CGFloat rowHeight; // 默认是 UITableViewAutomaticDimension,通过UITableViewAutomaticDimension 常量支持自适应高度的单元格

具体参看iOS 8自适应高度单元格问题

9、设置分组样式时的头视图高度(当代理方法没有实现时才有效)

tableView.sectionHeaderHeight = 40; 

@property (nonatomic) CGFloat sectionHeaderHeight; // default is UITableViewAutomaticDimension

10、设置分组样式时的尾视图高度(当代理方法没有实现时才有效)

tableView.sectionFooterHeight = 40;

@property (nonatomic) CGFloat sectionFooterHeight; // default is UITableViewAutomaticDimension

11、设置一个行高的估计值

tableView.estimatedRowHeight= 40;

@property (nonatomic) CGFloat estimatedRowHeight; // default is UITableViewAutomaticDimension


12、设置分组样式时的头视图的估计值

tableView.estimatedSectionHeaderHeight=40;

@property (nonatomic) CGFloat estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable

13、设置分组样式时的尾视图的估计值

tableView.estimatedSectionFooterHeight=40;

@property (nonatomic) CGFloat estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable

14、设置cell的分割线左对齐

在iOS7之前是没有这个设置,所以要加下判断。以免程序在iOS7之前的环境下运行崩溃。if([[[UIDevicecurrentDevice] systemVersion] floatValue] >=7) {

self.tableView.separatorInset =UIEdgeInsetsMake(0,0,0,0);

}

@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; 

备注:

iOS8 设置方法

-(void)viewDidLayoutSubviews {

if([self.mytableview respondsToSelector:@selector(setSeparatorInset:)]) {

[self.mytableview setSeparatorInset:UIEdgeInsetsZero];

}

if([self.mytableview respondsToSelector:@selector(setLayoutMargins:)]) {

[self.mytableview setLayoutMargins:UIEdgeInsetsZero];

}

}

-(void)tableView:(UITableView*)tableView willDisplayCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPat{

if([cell respondsToSelector:@selector(setLayoutMargins:)]) {

[cell setLayoutMargins:UIEdgeInsetsZero];

}if([cell respondsToSelector:@selector(setSeparatorInset:)]){

[cell setSeparatorInset:UIEdgeInsetsZero];

}

}

具体参看:iOS Tableview SeparatorInset Cell分割线左对齐

15、自定义一个cell分割线的边距

typedefNS_ENUM(NSInteger,UITableViewSeparatorInsetReference) {

UITableViewSeparatorInsetFromCellEdges,//默认值,表示separatorInset是从cell的边缘的偏移量

UITableViewSeparatorInsetFromAutomaticInsets//表示separatorInset属性值是从一个insets的偏移量

}API_AVAILABLE(ios(11.0), tvos(11.0));

 tabelView.separatorInsetReference=UITableViewSeparatorInsetFromCellEdges; 

@property (nonatomic) UITableViewSeparatorInsetReference separatorInsetReference API_AVAILABLE(ios(11.0), tvos(11.0)); //更改自定义分隔符值的解释方式。默认值是UITableViewSeparatorInsetFromCellEdges

16、设置tableView的背景视图

UIImageView*imageView = [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"BackgroundImage"]];

self.tableView.backgroundView = imageView;

@property (nonatomic, strong, nullable) UIView *backgroundView NS_AVAILABLE_IOS(3_2); // 

备注:设置背景色

self.tableView.backgroundView优先级高,如果要设置backgroundColor的时候要先把view设置为nil

self.tableView.backgroundColor

17、获取section个数(只读属性)

NSInteger number=tableView.numberOfSections;

@property (nonatomic, readonly) NSInteger numberOfSections;//只读属性

18、设置每个section的行数

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

return 10;  

- (NSInteger)numberOfRowsInSection:(NSInteger)section;

19、返回指定section的矩形

 CGRect sectionRect = [self.tableView rectForSection:self.section];

- (CGRect)rectForSection:(NSInteger)section; //包含头部、尾部视图和当前section所有cell

20、返回section的header矩形

 CGRect sectionRect = [self.tableView rectForHeaderInSection:self.section];

- (CGRect)rectForHeaderInSection:(NSInteger)section;

21、返回section的rectForFooterInSection矩形

CGRect sectionRect = [self.tableView rectForFooterInSection:self.section];

- (CGRect)rectForFooterInSection:(NSInteger)section;

22、返回indexPath指定行的矩形

CGRect sectionRect = [self.tableView rectForRowAtIndexPath:self.indexPath];

- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;

23、根据一个几何点返回indexPath,如果超过边界返回nil

-(void)clickCommentLabelAction:(UIGestureRecognizer *)gestureRecognizer {  

CGPointcurrentTouchPosition=[gestureRecognizer locationInView:self.tableView];  

NSIndexPath *indexPath=[self.tableView indexPathForRowAtPoint:currentTouchPosition];  

    [self creatInputBox:indexPath];   

}  

- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;

24、根据cell返回它的indexPath

NSIndexPath *indexpath1 = [self.tableView indexPathForCell:cell];  

- (nullable NSIndexPath *)indexPathForCell:(UITableViewCell *)cell; // 如果cell不可用返回nil

25、 根据一个几何的矩形返回矩形所覆盖的行,返回是一个indexPath数组

        NSArray *temp = [tableView indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)];

- (nullable NSArray<NSIndexPath *> *)indexPathsForRowsInRect:(CGRect)rect; //如果rect无效,返回nil。

22、根据IndexPath返回cell

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

- (nullable __kindof UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath; //如果单元格不可见或索引路径超出范围,返回nil。

26、当前显示的cell 返回值是数组 

NSArray *cellArr = tableView.visibleCells;  

@property (nonatomic, readonly) NSArray<__kindof UITableViewCell *> *visibleCells;//只读属性

25、当前显示的cell的 indexPath,返回值是数组 

NSArray *indexPathArr = tableView.indexPathsForVisibleRows;  

@property (nonatomic, readonly, nullable) NSArray *indexPathsForVisibleRows;//只读属性

26、返回section对应的头部视图

UITableViewHeaderFooterView *headerView = [tableView headerViewForSection:indexPath.section];

- (nullable UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

27、返回section对应的尾部视图

UITableViewHeaderFooterView *headerView = [tableView footerViewForSection:indexPath.section];

- (nullable UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

28、滚动到指定位置

typedefNS_ENUM(NSInteger,UITableViewScrollPosition) {

UITableViewScrollPositionNone,//同UITableViewScrollPositionTop UITableViewScrollPositionTop,//定位完成后,将定位的行显示在tableView的顶部 UITableViewScrollPositionMiddle,//定位完成后,将定位的行显示在tableView的中间 UITableViewScrollPositionBottom//定位完成后,将定位的行显示在tableView最下面

};

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.lastIdx inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];  

- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;//indexPah参数是定位的位置,决定于分区和行号。animated参数决定是否有动画。scrollPosition参数决定定位的相对位置,它使一个枚举

29、使表格示图定位到选中行

typedefNS_ENUM(NSInteger,UITableViewScrollPosition) {

UITableViewScrollPositionNone,//同UITableViewScrollPositionTop UITableViewScrollPositionTop,//定位完成后,将定位的行显示在tableView的顶部 UITableViewScrollPositionMiddle,//定位完成后,将定位的行显示在tableView的中间 UITableViewScrollPositionBottom//定位完成后,将定位的行显示在tableView最下面

};

[self.tableView scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionMiddle animated:NO];  

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

30、将多个insert、delete、reload和move操作作为一个组进行动画处理

[tableView performBatchUpdates:^{

            [coordinator.items enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

                if(!obj) {

                    return;

                }

                NSIndexPath *indexPath = obj.sourceIndexPath;

                ListModel *model = self.dataSource[indexPath.row];

                [self.dataSource removeObject:model];

                [self.dataSource insertObject:model

                                      atIndex:destinationIndexPath.row];

                [tableView moveRowAtIndexPath:indexPath

                                  toIndexPath:destinationIndexPath];

            }];

        } completion:nil];

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

//updates

执行相关插入、删除、重新加载或移动操作的块。

completion当所有操作完成时,一个完成处理程序块将执行。此块没有返回值,并获取以下参数:

finished

一个布尔值,指示动画是否成功完成。如果动画因为任何原因被中断,则此参数的值为NO。

31、开始块标志

[tab beginUpdates]; 

- (void)beginUpdates;//

31、结束快标志

[tab endUpdates]; 

- (void)endUpdates;

备注:

当我们调用的上面的函数时,tableView会立刻调用代理方法进行刷新,如果其中我们所做的操作是删除某行,而然数据源数组我们可能并没有刷新,程序就会崩溃掉,原因是代理返回的信息和我们删除后不符。IOS为我们提供了上面两个函数解决这个问题:

具体参看:UITableView 属性用法详解

32、插入分区

animation参数是一个枚举,枚举的动画类型如下typedefNS_ENUM(NSInteger,UITableViewRowAnimation) {

UITableViewRowAnimationFade,//淡入淡出

 UITableViewRowAnimationRight,//从右滑入

 UITableViewRowAnimationLeft,//从左滑入

 UITableViewRowAnimationTop,//从上滑入

 UITableViewRowAnimationBottom,//从下滑入

 UITableViewRowAnimationNone,//没有动画

 UITableViewRowAnimationMiddle,

UITableViewRowAnimationAutomatic=100// 自动选择合适的动画

};

[tableView insertSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];

- (void)insertSections:(NSIndexSet*)sections withRowAnimation:(UITableViewRowAnimation)animation;//插入一个特定的分组。如果,指定的位置上已经存在了分组,那么原来的分组向后移动一个位置。

33、删除制定位置的分组

animation参数是一个枚举,枚举的动画类型如下typedefNS_ENUM(NSInteger,UITableViewRowAnimation) {

UITableViewRowAnimationFade,//淡入淡出

 UITableViewRowAnimationRight,//从右滑入

 UITableViewRowAnimationLeft,//从左滑入

 UITableViewRowAnimationTop,//从上滑入

 UITableViewRowAnimationBottom,//从下滑入

 UITableViewRowAnimationNone,//没有动画

 UITableViewRowAnimationMiddle,

UITableViewRowAnimationAutomatic=100// 自动选择合适的动画

};

 [tableView deleteSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];

- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;//删除一个制定位置的分组,其后面的分组向前移动一个位置。

34、重载制定位置的分区

animation参数是一个枚举,枚举的动画类型如下typedefNS_ENUM(NSInteger,UITableViewRowAnimation) {

UITableViewRowAnimationFade,//淡入淡出

 UITableViewRowAnimationRight,//从右滑入

 UITableViewRowAnimationLeft,//从左滑入

 UITableViewRowAnimationTop,//从上滑入

 UITableViewRowAnimationBottom,//从下滑入

 UITableViewRowAnimationNone,//没有动画

 UITableViewRowAnimationMiddle,

UITableViewRowAnimationAutomatic=100// 自动选择合适的动画

};

[self.tableView reloadSections:[NSIndexSetindexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];

- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);

35、移动分组

[tableView moveSection:1 toSection:0];

- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;//移动原来的分组从一个位置移动到一个新的位置。如果,新位置上若存在某个分组,那这某个分组将会向上(下)移动到临近一个位置。该方法,没有动画参数。会直接移动。并且一次只能移动一个分组。

36、插入指定的行

animation参数是一个枚举,枚举的动画类型如下typedefNS_ENUM(NSInteger,UITableViewRowAnimation) {

UITableViewRowAnimationFade,//淡入淡出

 UITableViewRowAnimationRight,//从右滑入

 UITableViewRowAnimationLeft,//从左滑入

 UITableViewRowAnimationTop,//从上滑入

 UITableViewRowAnimationBottom,//从下滑入

 UITableViewRowAnimationNone,//没有动画

 UITableViewRowAnimationMiddle,

UITableViewRowAnimationAutomatic=100// 自动选择合适的动画

};

[self.tableView insertRowsAtIndexPaths:insertArray withRowAnimation:UITableViewRowAnimationNone];

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;//在执行该方法时,会对数据源进行访问(分组数据和行数据),并更新可见行。所以,在调用该方法前,应该先更新数据源

37、删除一些行

animation参数是一个枚举,枚举的动画类型如下typedefNS_ENUM(NSInteger,UITableViewRowAnimation) {

UITableViewRowAnimationFade,//淡入淡出

 UITableViewRowAnimationRight,//从右滑入

 UITableViewRowAnimationLeft,//从左滑入

 UITableViewRowAnimationTop,//从上滑入

 UITableViewRowAnimationBottom,//从下滑入

 UITableViewRowAnimationNone,//没有动画

 UITableViewRowAnimationMiddle,

UITableViewRowAnimationAutomatic=100// 自动选择合适的动画

};

[self.tableView deleteRowsAtIndexPaths:deleIndexPaths withRowAnimation:UITableViewRowAnimationNone];

- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

38、重载一些行

animation参数是一个枚举,枚举的动画类型如下typedefNS_ENUM(NSInteger,UITableViewRowAnimation) {

UITableViewRowAnimationFade,//淡入淡出

 UITableViewRowAnimationRight,//从右滑入

 UITableViewRowAnimationLeft,//从左滑入

 UITableViewRowAnimationTop,//从上滑入

 UITableViewRowAnimationBottom,//从下滑入

 UITableViewRowAnimationNone,//没有动画

 UITableViewRowAnimationMiddle,

UITableViewRowAnimationAutomatic=100// 自动选择合适的动画

};

[tableview reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];

- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);

39、移动一行到另一行

 [tableView moveRowAtIndexPath:indexPath

                                  toIndexPath:destinationIndexPath];

- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath NS_AVAILABLE_IOS(5_0);

40、返回表视图是否包含删除占位符或重新排序它的行

 BOOL hasUncommittedUpdates =[tableView hasUncommittedUpdates];

@property (nonatomic, readonly) BOOL hasUncommittedUpdates API_AVAILABLE(ios(11.0), tvos(11.0));

41、刷新tableView

[tableView reloadData];

- (void)reloadData;

42、刷新索引栏

[tableView reloadSectionIndexTitles];

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

43、设置是否是编辑状态(编辑状态下的cell左边会出现一个减号,点击右边会划出删除按钮)

tableView.editing=YES;

@property (nonatomic, getter=isEditing) BOOL editing; // 默认是NO,没有动画

44、设置是否是编辑状态与动画

[tableView setEditing:YES animated:YES ];

- (void)setEditing:(BOOL)editing animated:(BOOL)animated;

45、设置cell是否可以被选中(默认为YES)

tableView.allowsSelection=YES;

@property (nonatomic) BOOL allowsSelection NS_AVAILABLE_IOS(3_0); // 默认是 YES.控制在不编辑模式下是否可以多选行。

45、设置UITableView编辑模式下是否可以被选中

tableView.allowsSelectionDuringEditing=YES;

@property (nonatomic) BOOL allowsSelectionDuringEditing; // 默认是 YES.控制在编辑模式下是否可以多选行。

46、设置是否支持多选

tableView.allowsMultipleSelection=YES;

@property (nonatomic) BOOL allowsMultipleSelection NS_AVAILABLE_IOS(5_0); // 默认是 NO.控制是否可以同时选择多个行。

47、设置在UITableView编辑模式是否支持多选

tableView.allowsMultipleSelectionDuringEditing=YES;

@property (nonatomic) BOOL allowsMultipleSelectionDuringEditing NS_AVAILABLE_IOS(5_0); // 默认是 NO.控制在编辑模式下是否可以同时选择多个行。

48、设置是否支持多选

tableView.allowsMultipleSelection=YES;

@property (nonatomic) BOOL allowsMultipleSelection NS_AVAILABLE_IOS(5_0); // 默认是 NO.控制是否可以同时选择多个行。

49、设置是否支持多选

tableView.allowsMultipleSelection=YES;

@property (nonatomic) BOOL allowsMultipleSelection NS_AVAILABLE_IOS(5_0); // 默认是 NO.控制是否可以同时选择多个行。

50、返回选定行的indexPath,单行

NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];  

@property (nonatomic, readonly, nullable) NSIndexPath *indexPathForSelectedRow; //返回表示区域和行选择的nil或索引路径,只读属性

51、返回选定行的indexPath数组,多行

        NSArray *temp = [tableView indexPathsForSelectedRows];

@property (nonatomic, readonly, nullable) NSArray <NSIndexPath *>*indexPathsForSelectedRows NS_AVAILABLE_IOS(5_0); //返回nil或一组表示选择的部分和行的索引路径,只读属性

52、设置默认选中某一行

typedefNS_ENUM(NSInteger,UITableViewScrollPosition) {

UITableViewScrollPositionNone,//同UITableViewScrollPositionTop UITableViewScrollPositionTop,//定位完成后,将定位的行显示在tableView的顶部 UITableViewScrollPositionMiddle,//定位完成后,将定位的行显示在tableView的中间 UITableViewScrollPositionBottom//定位完成后,将定位的行显示在tableView最下面

};

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0inSection:0];

    [mytableview selectRowAtIndexPath:[NSIndexPath indexPathForRow:0inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];

    if([mytableview.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) {

        [mytableview.delegate tableView:mytableview didSelectRowAtIndexPath:indexPath];

    }

- (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;//必须用户手动点击cell才会触发

53、取消tableView的选中状态

[tableView deselectRowAtIndexpath:selected animated:NO];

- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;

54、指定当tableView中多少行的时候开始显示IndexList,默认的设置是NSIntegerMax,即默认是不显示indexList的。

tableview.sectionIndexMinimumDisplayRowCount = 20;

@property (nonatomic) NSInteger sectionIndexMinimumDisplayRowCount; //显示某个组索引列表在右边当行数达到这个值,默认是NSInteger的最大值

55、索引条文字的颜色

[_tableView setSectionIndexColor:[UIColor darkGrayColor]];

@property (nonatomic, strong, nullable) UIColor *sectionIndexColor NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR;//选择某个部分的某行改变这一行上文本的颜色

56、索引条背景的颜色

[_tableView setSectionIndexBackgroundColor:[UIColor clearColor]];

@property (nonatomic, strong, nullable) UIColor *sectionIndexBackgroundColor NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; //在未被触摸的情况下,部分索引的背景颜色。

57、设置选中时,索引背景颜色

tableView.sectionIndexTrackingBackgroundColor = [UIColor grayColor];

@property (nonatomic, strong, nullable) UIColor *sectionIndexTrackingBackgroundColor NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR; //当它被触摸时,他的背景颜色。

58、设置有无分割线以及分割线的风格

typedef NS_ENUM(NSInteger, UITableViewCellSeparatorStyle) {

    UITableViewCellSeparatorStyleNone,// 没有分割线

    UITableViewCellSeparatorStyleSingleLine,// 单线,默认

    UITableViewCellSeparatorStyleSingleLineEtched NS_ENUM_DEPRECATED_IOS(2_0, 11_0, "Use UITableViewCellSeparatorStyleSingleLine for a single line separator.")//ios11之后废弃

} __TVOS_PROHIBITED;

 tableview.separatorStyle = UITableViewCellSeparatorStyleNone;

@property (nonatomic) UITableViewCellSeparatorStyle separatorStyle __TVOS_PROHIBITED; // 默认是 UITableViewCellSeparatorStyleSingleLine

59、设置选中单元格分隔线的颜色

    tableview.separatorColor = [UIColor colorWithRed:0/255.0 green:255/255.0 blue:0/255.0 alpha:255/255.0];

@property (nonatomic, strong, nullable) UIColor *separatorColor UI_APPEARANCE_SELECTOR __TVOS_PROHIBITED; //默认是标准的分隔符灰色。

60、设置tableView的蒙层效果

tableview.backgroundView = [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"detail.jpg"]];

UIBlurEffect*blurEffect = [UIBlurEffecteffectWithStyle:UIBlurEffectStyleDark];

UIVibrancyEffect*vibrancyEffect = [UIVibrancyEffecteffectForBlurEffect:blurEffect];

tableview.separatorEffect = vibrancyEffect;//为tableView设置一张背景图,然后通过UIBlurEffect[蒙层效果]创建一个对象赋给tableView的separatorEffect属性,并且将Cell的背景色设置为clearColor,即可获得非常酷炫的半透明Cell效果了

@property (nonatomic, copy, nullable) UIVisualEffect *separatorEffect NS_AVAILABLE_IOS(8_0) UI_APPEARANCE_SELECTOR __TVOS_PROHIBITED; //适用于表分隔符的效果。

61、处理tableview在iPad上显示不全问题

_tableView.cellLayoutMarginsFollowReadableWidth = NO;

@property (nonatomic) BOOL cellLayoutMarginsFollowReadableWidth NS_AVAILABLE_IOS(9_0);

62、设置tableview的contentView是否受到安全区域的限制

[tableView  setInsetsContentViewsToSafeArea:NO];

@property (nonatomic) BOOL insetsContentViewsToSafeArea API_AVAILABLE(ios(11.0), tvos(11.0)); // 默认是 YES

63、设置组表的头标签视图

    tableview.tableHeaderView = [UIButton buttonWithType:UIButtonTypeContactAdd];

@property (nonatomic, strong, nullable) UIView *tableHeaderView; 

备注:

因为 self.tableView.tableHeaderView的高度是没有办法设置的,所以必须设置自定义View的高度 来达到设置 self.tableView.tableHeaderView的高度

64、设置组表的尾标签视图

    tableview.tableFooterView = [UIButton buttonWithType:UIButtonTypeContactAdd];

@property (nonatomic, strong, nullable) UIView *tableFooterView; 

二、UITableView的重用属性

1、获取重用队列里的单元格

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];

- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; //委托用于获取已分配的单元格,而不是分配新的单元格。

2、从队列中取出单元格

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];

- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);

备注:

上面两个方法都可以获取重用队列里的单元格,不过是有区别的。

具体参看:UITableViewCell两个复用方法的区别

3、UITableView的cellXib注册

     [tableView registerNib:nib forCellReuseIdentifier:identy];  

- (void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);

4、UITableView的UITableViewCell注册   

 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];

- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

5、用Xib注册分组头尾视图

     [tableView registerNib:nib forHeaderFooterViewReuseIdentifier:identy];  

- (void)registerNib:(nullable UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

6、用类注册分组头尾视图

 [self.tableView registerClass:[UITableViewCell class] forHeaderFooterViewReuseIdentifier:@"cell"];

- (void)registerClass:(nullable Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

7、设置是否自动将焦点分配到最后一个焦点索引路径上的项

tableView.remembersLastFocusedIndexPath=YES;

@property (nonatomic) BOOL remembersLastFocusedIndexPath NS_AVAILABLE_IOS(9_0); //默认为NO。如果YES,当聚焦一个表格视图,上一个索引路径自动聚焦。如果从来没有集中的表视图,那么首选集中使用索引路径。

8、设置TableView的是否开启拖放功能

tableView.dragInteractionEnabled=YES;

@property (nonatomic) BOOL dragInteractionEnabled API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);//dragInteractionEnabled 属性在 iPad 上默认是YES,在 iPhone 默认是 NO,只有设置为 YES 才可以进行 drag 操作

9、获取指示是否从表视图中取消行,且尚未删除

BOOL hasActiveDrag=tableView.hasActiveDrag;

@property (nonatomic, readonly) BOOL hasActiveDrag API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);

10、获取指示集合视图当前是否正在跟踪一个drop会话

BOOL hasActiveDrop=tableView.hasActiveDrop;

@property (nonatomic, readonly) BOOL hasActiveDrop API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);

三、UITableView的UITableViewDataSource属性

1、返回   对应的section有多少个元素--必须要实现的方法

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

return 1;

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

2、 返回指定的row 的cell--必须要实现的方法

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

    EOPageModel *model = self.dataArr[indexPath.section];

    EORightArrowCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EORightArrowCell"];

    cell.title = model.name;

    return cell;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

3、返回 tableview 有多少个section

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

    return 3;

}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; // 默认是1

4、返回指定的section 的 header  的 title,如果这个section header  有返回view,那么title就不起作用了。

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section  {  

return @"title 1";  

    }  

- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; //固定的字体样式。如果您想要一些不同的东西,可以使用自定义视图(UILabel)。

5、返回指定的section 的 footer  的 title,如果这个section footer  有返回view,那么title就不起作用了。

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section  {  

return @"title 1";  

    }  

- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; //固定的字体样式。如果您想要一些不同的东西,可以使用自定义视图(UILabel)。

6、这个回调决定了在当前indexPath的Cell是否可以编辑

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{

return YES;

}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;

7、这个回调决定了在当前indexPath的Cell是否可以移动

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{

return YES;

}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;

8、右边索引 字节数(如果不实现 就不显示右侧索引)

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {

return sectionTitleArray;

}

- (nullable NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; // return list of section titles to display in section index view (e.g. "ABCD...Z#")

9、点击右侧索引表项时调用

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {

  NSString *key = [sectionTitleArray objectAtIndex:index];

  NSLog(@"sectionForSectionIndexTitle key=%@",key);

  if (key == UITableViewIndexSearch) {

    [listTableView setContentOffset:CGPointZero animated:NO];

    return NSNotFound;

  }

return index;

}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; // tell table which section corresponds to section title/index (e.g. "B",1))

10、实现了此方法向左滑动就会显示删除按钮

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{

    KCContactGroup *group =_contacts[indexPath.section];

    KCContact *contact=group.contacts[indexPath.row];

    if (editingStyle==UITableViewCellEditingStyleDelete) {

        [group.contacts removeObject:contact];

        //考虑到性能这里不建议使用reloadData

        //[tableView reloadData];

        //使用下面的方法既可以局部刷新又有动画效果

        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom];

        //如果当前组中没有数据则移除组刷新整个表格

        if (group.contacts.count==0) {

            [_contacts removeObject:group];

            [tableView reloadData];

        }

    }

}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;

11、只要实现这个方法在编辑状态右侧就有排序图标

-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{

    KCContactGroup *sourceGroup =_contacts[sourceIndexPath.section];

    KCContact *sourceContact=sourceGroup.contacts[sourceIndexPath.row];

    KCContactGroup *destinationGroup =_contacts[destinationIndexPath.section];


    [sourceGroup.contacts removeObject:sourceContact];

    if(sourceGroup.contacts.count==0){

        [_contacts removeObject:sourceGroup];

        [tableView reloadData];

    }

    [destinationGroup.contacts insertObject:sourceContact atIndex:destinationIndexPath.row];

}

 四、UITableView的UITableViewDataSourcePrefetching属性

1、设置预读取的优先排序数组

- (void)tableView:(UITableView*)tableView prefetchRowsAtIndexPaths:(NSArray *)indexPaths{

for (NSIndexPath * indexPath in indexPaths) { 

NSURL *currentURL = [self.imgURLArray objectAtIndex:indexPath.row]; 

//不存在就请求 

if (!self.imgs[currentURL]) { 

[self loadImage:indexPath]; 

}

- (void)tableView:(UITableView*)tableView prefetchRowsAtIndexPaths:(NSArray *)indexPaths;

2、 取消提前加载数据 

- (void)tableView:(UITableView *)tableView cancelPrefetchingForRowsAtIndexPaths:(NSArray *)indexPaths{

for (NSIndexPath * indexPath in indexPaths){ 

NSURL *currentURL = [self.imgURLArray objectAtIndex:indexPath.row]; 

//当前任务存在 

if (self.tasks[currentURL]) { 

dispatch_queue_t queue = self.tasks[currentURL]; 

dispatch_suspend(queue); 

self.tasks[currentURL] = nil; 

- (void)tableView:(UITableView *)tableView cancelPrefetchingForRowsAtIndexPaths:(NSArray *)indexPaths;

 五、UITableView的UITableViewDragDelegate属性

1、提供一个 给定 indexPath 的可进行 drag 操作的 item(类似 hitTest: 方法周到该响应的view )如果返回 nil,则不会发生任何拖拽事件

- (NSArray*)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id)session atIndexPath:(NSIndexPath *)indexPath{

    NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithObject:self.dataSource[indexPath.item]];

    UIDragItem *item = [[UIDragItem alloc] initWithItemProvider:itemProvider];

    self.dragIndexPath = indexPath;

    return@[item];

}

- (NSArray*)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id)session atIndexPath:(NSIndexPath *)indexPath;

2、当接收到添加item响应时,会调用该方法向已经存在的drag会话中添加item

- (NSArray*)tableView:(UITableView *)tableView itemsForAddingToDragSession:(id)session atIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point{

  NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithObject:self.dataSource[indexPath.item]];

    UIDragItem *item = [[UIDragItem alloc] initWithItemProvider:itemProvider];

    return@[item];

}

- (NSArray*)tableView:(UITableView *)tableView itemsForAddingToDragSession:(id)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{

  // 可以在该方法内使用 贝塞尔曲线 对单元格的一个具体区域进行裁剪

    UIDragPreviewParameters *parameters = [[UIDragPreviewParameters alloc] init];


    CGFloat previewLength = self.flowLayout.itemSize.width;

    CGRect rect = CGRectMake(0, 0, previewLength, previewLength);

    parameters.visiblePath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:5];

    parameters.backgroundColor = [UIColor clearColor];

    returnparameters;

}

- (nullable UIDragPreviewParameters *)tableView:(UITableView *)tableView dragPreviewParametersForRowAtIndexPath:(NSIndexPath *)indexPath;

4、开始拖拽之前会调用该方法(与dragSessionDidEnd一起使用)

- (void)tableView:(UITableView *)tableView dragSessionWillBegin:(id)session{

    NSLog(@"dragSessionWillBegin --> drag 会话将要开始");

}

- (void)tableView:(UITableView *)tableView dragSessionWillBegin:(id)session;

5、拖拽结束的时候会调用该方法

- (void)tableView:(UITableView *)tableView dragSessionDidEnd:(id)session{

    NSLog(@"dragSessionDidEnd --> drag 会话已经结束");

}

- (void)tableView:(UITableView *)tableView dragSessionDidEnd:(id)session;

6、控制拖动会话是否允许移动操作(默认是yes)

- (BOOL)tableView:(UITableView *)tableView dragSessionAllowsMoveOperation:(id)session{

return YES;

}

- (BOOL)tableView:(UITableView *)tableView dragSessionAllowsMoveOperation:(id)session;

7、控制拖动会话是否仅限于源应用程序(默认是no)

- (BOOL)tableView:(UITableView *)tableView dragSessionIsRestrictedToDraggingApplication:(id)session{

return YES;

}

- (BOOL)tableView:(UITableView *)tableView dragSessionIsRestrictedToDraggingApplication:(id)session;

 五、UITableView的UITableViewDropDelegate属性

1、使用 dropCoordinator 去置顶如果处理当前 drop 会话的item 到指定的最终位置, 同时也会根据drop item返回的数据更新数据源(把TableView的拖放功能给打开)

- (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id)coordinator{

 if(!coordinator) {

        return;

    }

    NSIndexPath *destinationIndexPath = coordinator.destinationIndexPath;

    dispatch_async(dispatch_get_main_queue(), ^{

        [tableView performBatchUpdates:^{

            [coordinator.items enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

                if(!obj) {

                    return;

                }

                NSIndexPath *indexPath = obj.sourceIndexPath;

                ListModel *model = self.dataSource[indexPath.row];

                [self.dataSource removeObject:model];

                [self.dataSource insertObject:model

                                      atIndex:destinationIndexPath.row];

                [tableView moveRowAtIndexPath:indexPath

                                  toIndexPath:destinationIndexPath];

            }];

        } completion:nil];

    });

}

- (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id)coordinator;

2、判断对应的item 能否被 执行drop会话

- (BOOL)tableView:(UITableView *)tableView canHandleDropSession:(id)session{

return YES;

}

- (BOOL)tableView:(UITableView *)tableView canHandleDropSession:(id)session;

3、当drop会话进入到 tableView 的坐标区域内就会调用

- (void)tableView:(UITableView *)tableView dropSessionDidEnter:(id)session{

    NSLog(@"dropSessionDidEnter --> dropSession进入目标区域");

}

- (void)tableView:(UITableView *)tableView dropSessionDidEnter:(id)session;

4、提供释放方案的方法

- (UITableViewDropProposal *)tableView:(UITableView *)tableView dropSessionDidUpdate:(id)session withDestinationIndexPath:(nullable NSIndexPath *)destinationIndexPath{

    if (session.localDragSession) {

        dropProposal = [[UITableViewDropProposal alloc] initWithDropOperation:UIDropOperationCopy intent:UITableViewDropIntentInsertAtDestinationIndexPath];

    } else {

        dropProposal = [[UITableViewDropProposal alloc] initWithDropOperation:UIDropOperationCopy intent:UITableViewDropIntentInsertAtDestinationIndexPath];

    }

    return dropProposal;

}

- (UITableViewDropProposal *)tableView:(UITableView *)tableView dropSessionDidUpdate:(id)session withDestinationIndexPath:(nullable NSIndexPath *)destinationIndexPath;

5、当 dropSession 不在tableView 目标区域的时候会被调用

- (void)tableView:(UITableView *)tableView dropSessionDidExit:(id)session{

    NSLog(@"dropSessionDidExit --> dropSession 离开目标区域");

}

- (void)tableView:(UITableView *)tableView dropSessionDidExit:(id)session;

6、 当dropSession 完成时会被调用(适合在这个方法里做一些清理的操作)

- (void)tableView:(UITableView *)tableView dropSessionDidEnd:(id)session {

    NSLog(@"dropSessionDidEnd --> dropSession 已完成");

}

- (void)tableView:(UITableView *)tableView dropSessionDidEnd:(id)session;

7、当 item 执行drop 操作的时候,可以自定义预览图,如果没有实现该方法或者返回nil,整个cell将会被用于预览图

- (nullable UIDragPreviewParameters *)tableView:(UITableView *)tableView dropPreviewParametersForRowAtIndexPath:(NSIndexPath *)indexPath{

return nil;

}

- (nullable UIDragPreviewParameters *)tableView:(UITableView *)tableView dropPreviewParametersForRowAtIndexPath:(NSIndexPath *)indexPath;

 六、UITableView的UITableViewDropProposal属性

1、初始化方法

        dropProposal = [[UITableViewDropProposal alloc] initWithDropOperation:UIDropOperationCopy intent:UITableViewDropIntentInsertAtDestinationIndexPath];

- (instancetype)initWithDropOperation:(UIDropOperation)operation intent:(UITableViewDropIntent)intent;

2、设置DropIntent

typedef NS_ENUM(NSInteger, UITableViewDropIntent) {

    UITableViewDropIntentUnspecified,// 将会接收drop,但是具体的位置要稍后才能确定;不会开启一个缺口,可以通过添加视觉效果给用户传达这一信息

    UITableViewDropIntentInsertAtDestinationIndexPath,//将会被插入到目标索引中;将会打开一个缺口,模拟最后释放后的布局

    UITableViewDropIntentInsertIntoDestinationIndexPath,//将会释放在目标索引路径,比如该cell是一个容器(集合),此时不会像 ?? 那个属性一样打开缺口,但是该条目标索引对应的cell会高亮显示

   UITableViewDropIntentAutomatic//可以自动判断是放入文件夹还是打开缺口进入目标索引

} API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);

       dropProposal = [[UITableViewDropProposal alloc] initWithDropOperation:UIDropOperationCopy intent:UITableViewDropIntentInsertAtDestinationIndexPath];

@property (nonatomic, readonly) UITableViewDropIntent intent;

 七、UITableView的UITableViewDropCoordinator属性

1、@property (nonatomic, readonly) NSArray> *items;

2、@property (nonatomic, readonly, nullable) NSIndexPath *destinationIndexPath;

3、@property (nonatomic, readonly) UITableViewDropProposal *proposal;

4、@property (nonatomic, readonly) id session;

5、- (id)dropItem:(UIDragItem *)dragItem toPlaceholder:(UITableViewDropPlaceholder *)placeholder;

6、- (id)dropItem:(UIDragItem *)dragItem toRowAtIndexPath:(NSIndexPath *)indexPath;

7、- (id)dropItem:(UIDragItem *)dragItem intoRowAtIndexPath:(NSIndexPath *)indexPath rect:(CGRect)rect;

8、- (id)dropItem:(UIDragItem *)dragItem toTarget:(UIDragPreviewTarget *)target;

 八、UITableView的UITableViewPlaceholder属性

1、初始化方法

- (instancetype)initWithInsertionIndexPath:(NSIndexPath *)insertionIndexPath reuseIdentifier:(NSString *)reuseIdentifier rowHeight:(CGFloat)rowHeight NS_DESIGNATED_INITIALIZER;

2、@property (nonatomic, nullable, copy) void(^cellUpdateHandler)(__kindof UITableViewCell *);

九、UITableView的UITableViewDropPlaceholder属性

1、@property (nonatomic, nullable, copy) UIDragPreviewParameters * _Nullable (^previewParametersProvider)(__kindof UITableViewCell *);

十、UITableView的UITableViewDropItem属性

1、@property (nonatomic, readonly) UIDragItem *dragItem;

2、@property (nonatomic, readonly, nullable) NSIndexPath *sourceIndexPath;

3、@property (nonatomic, readonly) CGSize previewSize;

十一、UITableView的UITableViewDropPlaceholderContext属性

1、@property (nonatomic, readonly) UIDragItem *dragItem;

2、

- (BOOL)commitInsertionWithDataSourceUpdates:(void(NS_NOESCAPE ^)(NSIndexPath *insertionIndexPath))dataSourceUpdates;

3、- (BOOL)deletePlaceholder;

十二、UITableView的UITableViewRowAction属性

1、初始化方法

UITableViewRowAction*likeAction = [UITableViewRowActionrowActionWithStyle:UITableViewRowActionStyleNormaltitle:@"喜欢"handler:^(UITableViewRowAction* _Nonnull action,NSIndexPath* _Nonnull indexPath) {/

/ 实现相关的逻辑代码//

 ...

// 在最后希望cell可以自动回到默认状态,所以需要退出编辑模式tableView.editing =NO; 

 }];

+ (instancetype)rowActionWithStyle:(UITableViewRowActionStyle)style title:(nullable NSString *)title handler:(void (^)(UITableViewRowAction *action, NSIndexPath *indexPath))handler;

2、获取按钮的显示样式

typedef NS_ENUM(NSInteger, UITableViewRowActionStyle) {

    UITableViewRowActionStyleDefault = 0,//红色

    UITableViewRowActionStyleDestructive = UITableViewRowActionStyleDefault,//红色

    UITableViewRowActionStyleNormal//灰色

} NS_ENUM_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED;

 NSLog(@"%ld",(long)deleteAction.style);

@property (nonatomic, readonly) UITableViewRowActionStyle style;

3、设置侧滑按钮的标题

deleteAction.title=@"删除";

@property (nonatomic, copy, nullable) NSString *title;

4、设置侧滑按钮的背景颜色

deleteAction.backgroundColor = [UIColor colorFromHexCode:@"FF5C64"];

@property (nonatomic, copy, nullable) UIColor *backgroundColor; //默认背景颜色取决于样式。

5、设置侧滑按钮的毛玻璃效果

deleteAction.backgroundEffect=[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];

@property (nonatomic, copy, nullable) UIVisualEffect* backgroundEffect;

十三、UITableView的UITableViewFocusUpdateContext属性

1、上一个交互的索引

@property (nonatomic, strong, readonly, nullable) NSIndexPath *previouslyFocusedIndexPath;

2、下一个交互的索引

@property (nonatomic, strong, readonly, nullable) NSIndexPath *nextFocusedIndexPath;

十四、UITableView的UITableViewDelegate属性

1、cell将要显示

- (void)tableView:(UITableView *)tableView willDisplayCell:(nonnull UITableViewCell *)cell forRowAtIndexPath:(nonnull NSIndexPath *)indexPath {

    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {

        [tableView setSeparatorInset:UIEdgeInsetsZero];

    }

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {

        [tableView setLayoutMargins:UIEdgeInsetsZero];

    }

    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {

        [cell setLayoutMargins:UIEdgeInsetsZero];

    }

}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;

2、组头将要出现的时候系统会调用

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section{

 if(!_isUpScroll && (_currentSection - section) == 1){

       //最上面组头(不一定是第一个组头,指最近刚被顶出去的组头)又被拉回来

 _currentSection = section;

 NSLog(@"willDisplayHeaderView显示第%ld组",(long)section);

    }

}

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

3、组尾出现的时候系统会调用

- (void)tableView:(UITableView*)tableView willDisplayFooterView:(UIView*)view forSection:(NSInteger)section { view.tintColor = [UIColorclearColor];}

- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

4、在删除cell之后调用,停止显示cell的时候调用,界面不显示cell时

- (void)tableView:(UITableView*)tableView didEndDisplayingCell:(UITableViewCell*)cell forRowAtIndexPath:(NSIndexPath*)indexPath {

NSString*key = [NSStringstringWithFormat:@"%ld", (long)indexPath.row]; [self.heightDict setObject:@(cell.height) forKey:key];

 DEBUG_LOG(@"第%@行的计算的最终高度是%f",key,cell.height);

}

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);

5、每个section的header呈现完毕后回调

- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section{

 if(!_isFirstLoad && _isUpScroll){

 _currentSection = section + 1;

        //最上面的组头被顶出去

 NSLog(@"didEndDisplayingHeaderView显示第%ld组",(long)section + 1);

    }

}

- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

6、每个section的footer呈现完毕后回调

- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section{

 NSLog(@"didEndDisplayingFooterView显示第%ld组",(long)section + 1);

}

- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

7、设置行高

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return kSCRATIO(65);

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

8、设置Section的头部高度

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {

    return 0.01;

}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;

9、设置Section的尾部高度

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {

    return kSCRATIO(10);

}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;

10、估算cell的高度

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {

     return 88;

}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0);

11、估算Section的头部高度

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section{

     return 88;

}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);

12、估算Section的尾部高度

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section {

return 88;

}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0);

13、设置分区头视图 (自定义分区头 一定要设置分区头高度)

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    UITableViewHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"UITableViewHeaderFooterView"];

    if (!view) {

        view = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:@"UITableViewHeaderFooterView"];

        view.contentView.backgroundColor = colorFAFAFA;

    }

    return view;

}

- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; // custom view for header. will be adjusted to default or specified header height

14、设置分区尾视图 (自定义分区尾 一定要设置分区尾高度)

-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

{

    UIView *footerview = [[NSBundle mainBundle]loadNibNamed:@"myview" owner:self options:nil].firstObject;

    footerview.backgroundColor = [UIColor yellowColor];

    return footerview;

}

- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

15、 废弃的方法-设置右侧辅助按钮种类

- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;

16、响应,用户点击cell 右边的 箭头(如果有的话)

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath

{

    int  *idx = indexPath.row;

   //这里加入自己的逻辑

}

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;

17、当前选中的row是否高亮 

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {

return YES;

}

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);

18、cell高亮时调用的函数

- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {

}

- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);

19、cell取消高亮时调用的函数

- (void)tableView:(UITableView*)tableView didUnhighlightRowAtIndexPath:(NSIndexPath*)indexPath {

}

- (void)tableView:(UITableView*)tableView didUnhighlightRowAtIndexPath:(NSIndexPath*)indexPath;

20、将要选择指定索引处的表格行(适用于拦截点击某个cell)

- (nullable NSIndexPath*)tableView:(UITableView*)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {

 return indexPath;

}

- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;

21、将要取消某个cell(适用于拦截点击某个cell)

- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {

 return indexPath;

}

- (nullable NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);

22、cell点击事件

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    EOBalanceDetailVC *vc = [[EOBalanceDetailVC alloc] init];

    vc.model = self.dataArr[indexPath.row];

    [self.navigationController pushViewController:vc animated:YES];

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;

23、取消某个cell点击事件

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {

    EOWhiteCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    cell.titleL.textColor = Color7A7C85;

    cell.contentView.backgroundColor = C2;

}

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);

24、 返回指定索引位置表格行的编辑风格/样式

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

return UITableViewCellEditingStyleNone;

 }

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

25、返回指定索引处表格行上删除确认按钮上的标题文字 

-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{

return @删除;

}

- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;

26、指定索引行的表格行的编辑操作,返回UITableViewRowAction对象组成的数组

- (NSArray*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewRowAction* deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {

        EOPageModel *model = self.dataArr[indexPath.section];

        [self showHudWithHint:@""];

        [[MDDataCenter sharedInstance] NET_deletePageWithPageTemplateId:model.pageTemplateId success:^{

            [self hideHud];

            [self showHint:@"删除成功"];

            [self.dataArr removeObject:model];

            [self.tableView reloadData];

        } failure:^(EOErrorHandle *error) {

            [self hideHud];

            [self showHint:error.msg];

        }];

    }];

    deleteAction.backgroundColor = [UIColor colorFromHexCode:@"FF5C64"];

    return @[deleteAction];

}

- (nullable NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED;

27、cell的头部添加滑动的操作

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView

leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {

    UIContextualAction *contextualAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal

                                                                                   title:@"Copy"

                                                                                 handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void(^ _Nonnull completionHandler)(BOOL)) {

                                                                                     NSLog(@"Copy");

                                                                                 }];

    contextualAction.backgroundColor = [UIColor blackColor];

    UISwipeActionsConfiguration *swipeActionsCOnfiguration = [UISwipeActionsConfiguration configurationWithActions:@[contextualAction]];

    returnswipeActionsCOnfiguration;

}

- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);

28、滑动操作

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {

    //删除    UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:nil handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {

      //这里删除按钮点击或滑到最左侧时会触发这个回调      completionHandler (YES); //这里回调YES是执行删除操作  

  }];

    //下面的属性可以自定义删除的样式

    deleteRowAction.image = [UIImage imageNamed:@"address_cell_delete"];

    deleteRowAction.backgroundColor = [UIColor colorWithHexString:@"f4f4f4" alpha:1];

    UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction]];

    return config;

}

- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);

29、判断当编辑指定索引处的表格行时是否将要 indent(缩进,订货),默认所有的表格行编辑状态时都会缩进

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{

return YES;

}

- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;

30、将要开始编辑指定索引处的表格行

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath

{

 //setEditing:animated:前

}

- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath*)indexPath __TVOS_PROHIBITED;

31、指定索引处的表格行编辑完成

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath

{

 //setEditing:animated:后

}

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath __TVOS_PROHIBITED;

32、用户拖动某行sourceIndexPath经过目标行proposedDestinationIndexPath上方时,调用此函数询问是否可以移动,若不能移动则返回一个新的目的indexPath,否则直接返回proposedDestinationIndexPath,若无特别要求不需要实现

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath

{

if (proposedDestinationIndexPath.row ==5) {

 return [NSIndexPathindexPathForRow:8inSection:0];

    }

return proposedDestinationIndexPath;

}

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;

33、设置缩进的级别

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

    NSUInteger row = [indexPath row];

    return row;

}

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

34、是否将要显示指定索引处表格行的菜单

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath{

return YES;

};

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(5_0);

35、是否能使用 sender 对指定索引处列表行进行执行操作

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{

return YES;

};

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender NS_AVAILABLE_IOS(5_0);

36、通过 sender 对指定索引处的表格行执行操作

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender{

    if(action == @selector(copy:)) {

        UITableViewCell *cell = [_myTableView cellForRowAtIndexPath:indexPath];

        //创建粘贴板 UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];

        [pasteBoard setString:cell.textLabel.text];

    }

}

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender NS_AVAILABLE_IOS(5_0);

37、 返回能否获得焦点

- (BOOL)tableView:(UITableView *)tableView canFocusRowAtIndexPath:(NSIndexPath *)indexPath {

return YES;

};

- (BOOL)tableView:(UITableView *)tableView canFocusRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);

38、返回是否将要更新焦点

- (BOOL)tableView:(UITableView *)tableView shouldUpdateFocusInContext:(UITableViewFocusUpdateContext *)context {

return YES;

};

- (BOOL)tableView:(UITableView *)tableView shouldUpdateFocusInContext:(UITableViewFocusUpdateContext *)context NS_AVAILABLE_IOS(9_0);

39、 已经更新焦点时调用

- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator NS_AVAILABLE_IOS(9_0);

40、返回上一个焦点的indexPath

- (nullable NSIndexPath *)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView NS_AVAILABLE_IOS(9_0);

41、cell是否支持iOS11 新特性 Drag and Drop

- (BOOL)tableView:(UITableView *)tableView shouldSpringLoadRowAtIndexPath:(NSIndexPath *)indexPath withContext:(id)context {

return YES;

}

- (BOOL)tableView:(UITableView *)tableView shouldSpringLoadRowAtIndexPath:(NSIndexPath *)indexPath withContext:(id)context API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos, watchos);

参考

ios tableView那些事 (五) 给tableview设置缩进级别

iOS开发经验总结

iOS中UITableViewCell使用详解

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容