tableview的应用

UITableView简介
UITableView继承自UIScrollView,只支持垂直滚动。在iOS中的绝大部分表格数据展示,都可以由UITableView来完成。UITableView具有延迟加载和重用的特性,加载数据时不会一次加载完所有的数据,而是只加载当前被显示的内容,移出屏幕的单元格,被放到缓存池中等待重用

UITableView的常用方法与属性
常用方法
// 必须要指定tableView的style! -initWithFrame调用这个方法默认使用 UITableViewStylePlain
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;
// 重新读取tableView的所有数据
- (void)reloadData;
// 将指定行滚动到屏幕指定位置
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
// 选中指定行,并将其滚动到指定位置。不会触发代理方法,也不会发送cell被选中的系统通知
- (void)selectRowAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
// 取消选中指定行
- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;

与tableViewCell相关的方法
// 从缓存池中获取cell以替代新建cell,返回值可为nil(返回nil则需手动创建)
- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
// 从缓存池中获取cell。如未获取到,则根据storyboard中的原型cell、注册的xib或者class新建一个。
// 这个方法一定会返回cell。但必须保证cell的重用ID已经注册
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
// 从缓存池中获取分组的组头/组尾(tableView的分组header/footer也具有重用机制)
- (nullable __kindof UITableViewHeaderFooterView *)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier;
// 为cell/分组组头/分组组尾注册class/xib
- (void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier;
- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(nullable UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier;
- (void)registerClass:(nullable Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier;

常用属性
// 数据源对象。tableView展示数据的决定性属性
@property (nonatomicweak, nullable) id <UITableViewDataSource> dataSource;
// 代理对象。可以监听tableView的行为
@property (nonatomicweak, nullable) id <UITableViewDelegate> delegate;

// cell的统一行高,如不设置,默认为44
@property (nonatomicCGFloat rowHeight;
// 分组组头统一高度,plain样式默认为28,grouped样式默认为18
@property (nonatomicCGFloat sectionHeaderHeight;
// 同sectionHeaderHeight
@property (nonatomicCGFloat sectionFooterHeight;
// 默认为0。设置以下属性,可以让tableView快速预估读取时间。
// 设置以下属性,可以让延迟调用询问实际高度的方法,从而可以在那些方法中添加更重要的逻辑实现
@property  ( nonatomic CGFloat  estimatedRowHeight;
@property  ( nonatomic CGFloat  estimatedSectionHeaderHeight;
@property (nonatomicCGFloat estimatedSectionFooterHeight;

// 背景view。默认作为tableView的子控件,显示在tableView展示数据的底部,尺寸会自动适应tableView的尺寸。
@property (nonatomicstrong, nullable) UIView *backgroundView;
// 修改tableView编辑状态。修改此条属性,无动画效果。如需动画效果,使用 -setEditing:animated: 方法
@property (nonatomic, getter=isEditing) BOOL editing;
// 是否支持cell选中与多选
@property (nonatomicBOOL allowsSelection;
@property (nonatomicBOOL allowsMultipleSelection;
// 当前选中cell的坐标
@property (nonatomicreadonly, nullable) NSIndexPath *indexPathForSelectedRow;
// cell的分隔线样式
@property (nonatomicUITableViewCellSeparatorStyle separatorStyle;
// tableView的整体头部/尾部,是tableView自带的子控件,不是分组的组头/组尾
@property (nonatomicstrong, nullable) UIView *tableHeaderView;
@property (nonatomicstrong, nullable) UIView *tableFooterView;

tableView的其它功能方法
// 插入行
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
// 删除行
- (void)deleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
// 移动行
- (void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;

UITableViewDataSource数据源协议
@required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
// 实现这个方法时,必须要利用cell的重用机制节约性能!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

@optional
// 可以不实现,默认为1组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
// 分组组头/组尾的备注信息。如果需要设计自需样式,可以通过代理协议中的方法返回UIView控件
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
// 返回所有组索引标题在右侧,便于快捷跳转分组
- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// 一旦实现此方法,横向拖动cell会有操作选项,默认为删除
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// 移动指定行到目标行。目标行之前/后的cell依次后/前移
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

UITableViewDelegate代理协议
// 即将显示cell,以下方法类似的均还有sectionHeaderView/sectionFooterView
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
// 结束显示cell
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath;
// 动态获取每个cell的行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 动态获取每组组头view的高度。对于分组样式的tableView,这个方法必须实现,否则第一组组头无法显示!
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
// 动态获取每个cell的预估行高,很少用,一般设置统一行高
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
// 分组组头view,frame会采用默认组头的高度或者指定的高度。组尾view也类似
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

与tableView事件相关的代理协议方法
// cell可否高亮,是后两个方法的前提条件
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath;
// cell已经高亮
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath;
// cell解除高亮
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath;
// 即将/已经选中指定行。类似还有取消选中cell的方法
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// cell操作文字显示(与数据源协议中 -tableView:commitEditingStyle:forRowAtIndexPath方法关联)
- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;

UITableViewCell
cell的属性基本都属于懒加载,没有使用到的控件,不会创建。自定义cell时,基础类的子控件仍然存在,cell超类的子控件一旦被创建加载,其frame会根据cell的frame自动匹配适应。使用自定义cell时,应注意避免用到超类的子控件,比如imageView、textLabel等,自定义控件的属性名称也不要与超类属性控件名称重复!

cell常用属性
@property  ( nonatomic readonly strong , nullable)  UIImageView  *imageView;
@property (nonatomicreadonlystrong, nullable) UILabel *textLabel;
@property (nonatomicreadonlystrong, nullable) UILabel *detailTextLabel;
// 某些情况下,cell的内容需要进行位置调整(比如编辑时内容左移),因此需要将子控件添加到contentView中
// 如果将子控件添加到cell中,控件不会随cell内容移动而移动,会固定在cell中指定位置
@property (nonatomicreadonlystrongUIView *contentView;
// plain样式下默认为nil,grouped下不为nil,选中背景也类似。
@property (nonatomicstrong, nullable) UIView *backgroundView;
// 选中时的背景view
@property (nonatomicstrong, nullable) UIView *selectedBackgroundView;
// 多选被选中时的背景view。使用多选时,会取代selectedBackgroundView
@property (nonatomicstrong, nullable) UIView *multipleSelectionBackgroundView;
// 重用ID
@property (nonatomicreadonlycopy, nullable) NSString *reuseIdentifier;
// 系统自带样式附件,默认为nil
@property (nonatomicUITableViewCellAccessoryType    accessoryType;
// 自定义附件view。默认为nil,一旦设置,将取代系统自带的附件view
@property (nonatomicstrong, nullable) UIView       *accessoryView;
// 编辑状态附件view,类似于附件view
@property (nonatomicUITableViewCellAccessoryType    editingAccessoryType;
@property (nonatomicstrong, nullable) UIView       *editingAccessoryView;

//头文件
//  UITableView.h
//  UIKit
//
//  Copyright (c) 2005-2013, Apple Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import
<CoreGraphics/CoreGraphics.h>
#import
<UIKit/UIScrollView.h>
#import
<UIKit/UISwipeGestureRecognizer.h>
#import
<UIKit/UITableViewCell.h>
#import
<UIKit/UIKitDefines.h>

typedefNS_ENUM(NSInteger, UITableViewStyle) {
    UITableViewStylePlain,        
// regular table view不分组
    UITableViewStyleGrouped                
// preferences style table view(分组显示)
};

typedefNS_ENUM(NSInteger, UITableViewScrollPosition) {
    UITableViewScrollPositionNone, 
//没有效果
    UITableViewScrollPositionTop,   
//头部
    UITableViewScrollPositionMiddle,  
//中间
    UITableViewScrollPositionBottom  
//底部
};               
// scroll so row of interest is completely visible at top/center/bottom of view

typedefNS_ENUM(NSInteger, UITableViewRowAnimation) {
    UITableViewRowAnimationFade,
    UITableViewRowAnimationRight,          
//从右边插入或者删除每一行
    UITableViewRowAnimationLeft,           
//从左边开始插入每一行或者删除每一行
    UITableViewRowAnimationTop,            
//插入的时候向下移动,删除的时候向上移动(插入和删除始终从第一行开始)
    UITableViewRowAnimationBottom,         
//插入的时候向上移动,删除的时候向下移动(插入和删除始终从最后一行开始)
    UITableViewRowAnimationNone,           
// available in iOS 3.0
    UITableViewRowAnimationMiddle,         
// available in iOS 3.2.  attempts to keep cell centered in the space it will/did occupy
    UITableViewRowAnimationAutomatic =
100 // available in iOS 5.0.  chooses an appropriate animation style for you
};

UIKIT_EXTERN NSString *
constUITableViewIndexSearch NS_AVAILABLE_IOS(3_0);
UIKIT_EXTERN
constCGFloat UITableViewAutomaticDimension NS_AVAILABLE_IOS(5_0);

@classUITableView;
@classUINib;
@protocolUITableViewDataSource;
@classUILongPressGestureRecognizer;
@classUITableViewHeaderFooterView;
@classUIRefreshControl;

#pragma mark -代理方法
@protocolUITableViewDelegate <NSObject, UIScrollViewDelegate>//默认遵守基协议和ScrollView的协议,所以能滚动

@optional

#pragma mark @optional
#pragma mark
显示样式修改方式
//将要显示cell
- (
void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
//将要显示头部
- (
void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
//将要显示底部
- (
void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// cell已经显示完毕会调用
- (
void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0);
//头部部显示完毕
- (
void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
//底部显示完毕
- (
void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

#pragma mark返回cell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;//设置cell的行高
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;     
//设置顶部的高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;     
//设置底部的高度

//使用估算高度方法可以快速计算出高度值,这样可以加速table的加载速度
//如果这些方法被实现,上面的计算高度的方法将被推迟调用,直到views已经准备好被加载,所以耗费资源高的逻辑可以放在这里
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(
7_0);//返回某一行的估算高度,
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(
7_0);//返回某一组头部的高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(
7_0);//返回某一组底部的高度


//设置头部标题栏显示的控件
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
//设置底部栏显示的控件
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

#pragma mark右边辅助按钮
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath NS_DEPRECATED_IOS(2_0,3_0);
- (
void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;

#pragma mark Selection

//当点击某一行的时候,这个方法会被调用
- (
BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);//某一行是否是高亮显示
- (
void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);   //设置某一行高亮
- (
void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); //取消高亮

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(
3_0);
- (
void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;   //某一行在点击的时候调用的方法
- (
void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);// /某一行在取消点击的时候调用的方法

#pragma mark编辑
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;//编辑样式

- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(
3_0);//向左滑动时显示的文字

// Controls whether the background is indented while editing.  If not implemented, the default is YES.  This is unrelated to the indentation level below.  This method only applies to grouped style table views.
- (
BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;

// The willBegin/didEnd methods are called whenever the 'editing' property is automatically changed by the table (allowing insert/delete/move). This is done by a swipe activating a single row
- (
void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
- (
void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma mark Moving/reordering

// Allows customization of the target row for a particular row as it is being moved/reordered
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;   
//将某一行和另一行进行交换

#pragma mark Indentation

//缩进显示,只能对没有图片的行进行缩进,有图片的行,图片不会进行缩进
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;

//复制和粘贴时,下面的三个方法在设置代理的时候必须要求实现
- (
BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(5_0);
- (
BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0);
- (
void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0);

@end

UIKIT_EXTERN NSString *
constUITableViewSelectionDidChangeNotification;


//_______________________________________________________________________________________________________________
#pragma - mark声明部分
NS_CLASS_AVAILABLE_IOS(2_0)@interfaceUITableView : UIScrollView <NSCoding>

- (
id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style;               // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain

@property(nonatomic,readonly) UITableViewStyle           style;                //设置UITableView的样式
@property(nonatomic,assign)  id<UITableViewDataSource> dataSource;           //用来设置数据源
@property(nonatomic,assign)  id<UITableViewDelegate>   delegate;             //代理用来监听UITableView的点击
@property(nonatomic)          CGFloat                     rowHeight;            //行高,可以通过代码设置,默认是44
@property(nonatomic)          CGFloat                     sectionHeaderHeight;  //头部view的行高,默认是10
@property(nonatomic)          CGFloat                     sectionFooterHeight;  //底部view的行高,默认是10
@property(nonatomic)          CGFloat                     estimatedRowHeight NS_AVAILABLE_IOS(7_0);//默认是0,也就是没有公差
@property(nonatomic)          CGFloat                     estimatedSectionHeaderHeight NS_AVAILABLE_IOS(7_0);//默认是0,也就是没有公差
@property(nonatomic)          CGFloat                     estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0);//默认是0,也就是没有公差
@property(nonatomic)          UIEdgeInsets                separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;// allows customization of the frame of cell separators

@property(nonatomic,readwrite,retain) UIView *backgroundView NS_AVAILABLE_IOS(3_2);//

#pragma mark刷新数据

- (
void)reloadData;                //重新刷新所有数据
- (
void)reloadSectionIndexTitles NS_AVAILABLE_IOS(3_0);  //

#pragma mark Info

- (NSInteger)numberOfSections;                                 
//获取分了多少组
- (NSInteger)numberOfRowsInSection:(NSInteger)section;         
//获取某一组有多少行

- (CGRect)rectForSection:(NSInteger)section;                   
//返回某一组的形状,包括顶部、底部和所有行
- (CGRect)rectForHeaderInSection:(NSInteger)section;           
//返回某一组的顶部的形状
- (CGRect)rectForFooterInSection:(NSInteger)section;           
//返回某一组的底部的形状
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma - mark 按钮点击时,取得按钮的中心,通过此方法取得按钮所在的cell
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point;        //如果某一个点在某一行之外则返回空
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell;     
//如果某一个cell不可见则返回空
- (NSArray *)indexPathsForRowsInRect:(CGRect)rect;             
// returns nil if rect not valid

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;           
// returns nil if cell is not visible or index path is out of range
//可见的cell
- (NSArray *)visibleCells;
- (NSArray *)indexPathsForVisibleRows;
- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(
6_0);
- (UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(
6_0);

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

#pragma mark插入/删除/重新加载

- (
void)beginUpdates;  // allow multiple insert/delete of rows and sections to be animated simultaneously. Nestable
- (
void)endUpdates;    // only call insert/delete/reload calls or change the editing state inside an update block.  otherwise things like row count, etc. may be invalid.
#pragma - mark实现动态的打开和关闭某一组使用这些方法
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (
void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (
void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
- (
void)moveSection:(NSInteger)section toSection:(NSInteger)newSection NS_AVAILABLE_IOS(5_0);

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

- (
void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (
void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation NS_AVAILABLE_IOS(3_0);
- (
void)moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath NS_AVAILABLE_IOS(5_0);


@property(nonatomic,getter=isEditing)BOOLediting;                            // default is NO.
- (
void)setEditing:(BOOL)editing animated:(BOOL)animated;

@property(nonatomic)BOOLallowsSelection NS_AVAILABLE_IOS(3_0); //在非编辑模式下,控制每一行是否能被选择,默认YES
@property(nonatomic)BOOLallowsSelectionDuringEditing;                                 //默认NO.
@property(nonatomic)BOOLallowsMultipleSelection NS_AVAILABLE_IOS(5_0);                //默认NO.是否能够多选
@property(nonatomic)BOOLallowsMultipleSelectionDuringEditing NS_AVAILABLE_IOS(5_0);  // default is NO. Controls whether multiple rows can be selected simultaneously in editing mode

// Selection

- (NSIndexPath *)indexPathForSelectedRow;                      
//返回被选择行的IndexPath(空或者组号和行号)
- (NSArray *)indexPathsForSelectedRows NS_AVAILABLE_IOS(
5_0);  //返回被选择行(多行)的IndexPath(空或者组号和行号)装入的数组

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

#pragma mark -外观

@property(nonatomic) NSInteger sectionIndexMinimumDisplayRowCount;                                                     // show special section index list on right when row count reaches this value. default is 0
@property(nonatomic,retain) UIColor *sectionIndexColor NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR;                  // color used for text of the section index
@property(nonatomic,retain) UIColor *sectionIndexBackgroundColor NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;        // the background color of the section index while not being touched
@property(nonatomic,retain) UIColor *sectionIndexTrackingBackgroundColor NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR;// the background color of the section index while it is being touched

@property(nonatomic) UITableViewCellSeparatorStyle separatorStyle;  //行与行之间的分割线样式
@property(nonatomic,retain) UIColor               *separatorColor;  //分割线颜色

@property(nonatomic,retain) UIView *tableHeaderView;     //顶部的view子控件
@property(nonatomic,retain) UIView *tableFooterView;


- (
id)dequeueReusableCellWithIdentifier:(NSString *)identifier; //通过标识找出缓存池中的可重用的对象,而不会重新创建一个全新的对象
- (
id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);//通过标示符找到某一个特定的行数的cell
- (
id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); //通过标识从缓存池取出头部或者底部的view

//注册了nib以后,可以
- (
void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (
void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

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

@end


#pragma mark -数据源方法
@protocolUITableViewDataSource<NSObject>

@required
#pragma mark @required
//返回每一组的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
//返回每一行的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

@optional
#pragma mark @optional
//返回分组个数,不实现则默认是一组
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
//每一组顶部显示的标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
//每一组底部显示的标题
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;

#pragma mark编辑

//是否能被编辑
- (
BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma mark移动/重排序
// indexPath处的cell是否能被移动
- (
BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;

#pragma mark索引
//最右边显示的索引(e.g. "ABCD...Z#")
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; 
// tell table which section corresponds to section title/index (e.g. "B",1))

#pragma mark数据操作 插入和删除support
//如果实现了这个方法,就自动实现了滑动删除的功能,滑动的时候不会调用这个方法,在删除的时候才会调用这个方法(提交了一个删除操作会调用)
- (
void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;


- (
void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;//交换两个位置的cell

@end

//_______________________________________________________________________________________________________________


#pragma mark -这部分提供了简便的方法来使用NSIndexPath展示分组和行

@interfaceNSIndexPath (UITableView)

+ (NSIndexPath *)indexPathForRow:(NSInteger)row inSection:(NSInteger)section;
//返回一个带有行和分组信息的NSIndexPath对象

@property(nonatomic,readonly) NSInteger section;//分组
@property(nonatomic,readonly) NSInteger row;    //分行

@end





UITableView的两种样式
UITableViewStylePlain 不分组显示
UITableViewStyleGrouped 分组显示   

UITableViewDataSource  //数据源协议
两个必需实现的方法
//一组有多少行
- ( NSInteger )tableView:( UITableView *)tableView numberOfRowsInSection:( NSInteger )section
//每一行显示什么内容
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath

     /*
     24
(bit) 颜色
     Red : 8
个二进制位
     Green : 8
     Blue : 8
    
     32bit
颜色
     Alpha : 8
     Red : 8
     Green : 8
     Blue : 8
    
     //
每一个颜色通道占据 8 个二进制位, 所以一共有 24 位或者 32
     //
每一个颜色通道用 2 16 进制来表示,所以数值的取值范围就是【 0 255
     #ff ff ff  [0 255]
//        Red      Green     Blue
     #ff ff ff ff
    
     #77 23 88 ff
     用16进制来表示计算时用把16进制转换成10进制的数字来计算比例;
     */

   
   
// 设置分隔线颜色
   
self . tableView . separatorColor = [ UIColor colorWithRed : 35 / 255.0 green : 136 / 255.0 blue : 255 / 255.0 alpha : 119 / 255.0 ];
   
   
// 设置分隔线 style
//    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
   
   
// tableHeaderView 广告位
   
self . tableView . tableHeaderView = [[ UISwitch alloc ] init ];
   
// 加载更多
   
self . tableView . tableFooterView = [ UIButton buttonWithType : UIButtonTypeContactAdd ];

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

{

    // 1.定义一个cell的标识

      static NSString *ID = @"mjcell";

    // 2.从缓存池中取出cell

      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    // 3.如果缓存池中没有cell

      if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

    }

    // 4.设置cell的属性...

       return cell;



批量操作方法
// 允许在编辑模式进行多选操作

    self.tableView.allowsMultipleSelectionDuringEditing = YES;

 


 

 

- (IBAction)remove {

    // 获得所有被选中的行

    NSArray *indexPaths = [self.tableView indexPathsForSelectedRows];


    // 便利所有的行号

    NSMutableArray *deletedDeals = [NSMutableArray array];

    for (NSIndexPath *path in indexPaths) {

        [deletedDeals addObject:self.deals[path.row]];

    }

    

    // 删除模型数据

    [self.deals removeObjectsInArray:deletedDeals];

    

    // 刷新表格  一定要刷新数据

    [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];

}

 

--------------------------------------------------------------------

 

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

    // 取消选中

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

}

 

//开启编辑

[self.tableView setEditing:!self.tableView.editing animated:YES]; // 有动画

/**

 *  返回indexPath对应的编辑样式

 */

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

    if (tableView.isEditing) { // 如果是编辑模式,则返回插入操作

        return UITableViewCellEditingStyleInsert;

    }

    return UITableViewCellEditingStyleDelete;

}

//哪几行可以编辑

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

    if (indexPath.row > 4) {

        return NO;

    }

    return YES;

}

---------------------------------------------------------------------------

移动cell的方法

计算机生成了可选文字: i 巴 蜀 1 人 已 购 买

//移动cell方法

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

    //   如果原始位置与目标位置不相等   移动模型数组里的数据

    if (sourceIndexPath != destinationIndexPath) {

        //取出原始位置移动的那一行的模型

        id object = [self.contacts objectAtIndex:sourceIndexPath.row];

        //删除  数组中原始索引对应的模型    object

        [self.contacts removeObjectAtIndex:sourceIndexPath.row];

        if(destinationIndexPath.row > [self.contacts count]) { //如果目标位置大于数组的数量由于之前移除了一个模型  所以这里刚好模型数组的数量也减了1

            //如果目标位置大于数组数  就把模型直接添加到最后一个位置

            [self.contacts addObject:object];

        }

        else {

            //如果目标位置小于数组数  就把模型数据插入到数组对应目标位置的地方

            [self.contacts insertObject:object atIndex:destinationIndexPath.row];

        }

    }

    

    //更新数据

    [NSKeyedArchiver archiveRootObject:self.contacts toFile:FilePath];

    

}

 

//哪几行可以移动(可移动的行数小于等于可编辑的行数)

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

    if (indexPath.row > 5) {

        return NO;

    }

    return YES;

}

 

- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {

    

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

        

                NSLog(@"已删除");

            }];w

    

        UITableViewRowAction *actionSign = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注微信" handler:^(UITableViewRowAction * _Nonnullaction, NSIndexPath * _NonnullindexPath) {

        

                NSLog(@"标记关注");

            }];

        actionSign.backgroundColor = [UIColor blueColor];

    

        return @[action,actionSign];

}


全选按钮操作

- (
void )allSelect:( UIButton *)sender{
   
NSArray *anArrayOfIndexPath = [ NSArray arrayWithArray :[ table indexPathsForVisibleRows ]];
   
for ( int i = 0 ; i < [anArrayOfIndexPath count ]; i++) {
       
NSIndexPath *indexPath= [anArrayOfIndexPath objectAtIndex :i];
       
LTableViewCell *cell = ( LTableViewCell *)[ table cellForRowAtIndexPath :indexPath];
       
NSUInteger row = [indexPath row ];
       
NSLog ( @"%lu" ,( unsigned long )row);
       
NSMutableDictionary *dic = [ contacts objectAtIndex :row];
       
if ([[[( UIButton *)sender titleLabel ] text ] isEqualToString : @" 全选 " ]) {
            [dic
setObject : @"YES" forKey : @"checked" ];
            [cell
setChecked : YES ];
        }
else {
            [dic
setObject : @"NO" forKey : @"checked" ];
            [cell
setChecked : NO ];
        }
    }
   
if ([[[( UIButton *)sender titleLabel ] text ] isEqualToString : @" 全选 " ]){
       
for ( NSDictionary *dic in contacts ) {
            [dic
setValue : @"YES" forKey : @"checked" ];
        }
        [(
UIButton *)sender setTitle : @" 取消 " forState : UIControlStateNormal ];
    }
else {
       
for ( NSDictionary *dic in contacts ) {
            [dic
setValue : @"NO" forKey : @"checked" ];
        }
        [(
UIButton *)sender setTitle : @" 全选 " forState : UIControlStateNormal ];
    }
}
 

对UITableViewCell的分割线处理
// 通常做一次的操作都在 viewDidLoad
- (
void )viewDidLoad {
    [
super viewDidLoad ];
   
  
// 只要给 tableView 设置一个 footView 就能实现有数据的 Cell 才有分割线
   
self . tableView . tableFooterView = [[ UIView alloc ] init ];
   
}

// 每次重新布局控制器的 view 的子控件
- (
void )viewDidLayoutSubviews
{
    [
super viewDidLayoutSubviews ];

   
// 清空 tableView 分割线的内边距
    
self . tableView . separatorInset = UIEdgeInsetsZero ;
   
   
// 清空 tableView 约束的边缘
     [
self . tableView setLayoutMargins : UIEdgeInsetsZero ];
}


// tableView cell 即将显示的时候调用
- (
void )tableView:( UITableView *)tableView willDisplayCell:( UITableViewCell *)cell forRowAtIndexPath:( NSIndexPath *)indexPath
{
   
// 清空 cell 的约束边缘
    [cell
setLayoutMargins : UIEdgeInsetsZero ];

}

cell增加数据时单行刷新的bug
原因有两个一个是 [ self . tableView insertRowsAtIndexPaths : @[ path ] withRowAnimation : UITableViewRowAnimationFade ];
单行刷新时的一个动画问题 
还有就是cell里面的内容超出来cell的行高即超出了他父视图
解决的方法有两个种
  一: 关闭视图的动画:
     二:剪切超出父视图的边界的内容



cell重用的注意点:
重用时如果有按钮要注意刷新按钮的状态
一般在模型里添加一个BOOL  来保存他的状态  Cell重用的时候就重新刷新按钮的状态
//要在cell创建前注册即指定如何去创建
- ( void )viewDidLoad
{
    [
super viewDidLoad ];
     // 为表格注册可重用单元格( 告诉table View里的cell 以指定的 自定义cell 来创建 )
    [ self . tableView registerClass :[ XZSettingsCell class ] forCellReuseIdentifier : SettingsCellID ];

}

// 每行cell里的内容
- ( UITableViewCell *)tableView:( UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath
{
    // 从缓存区找指定的自定义的 cell
    XZSettingsCell *cell = [tableView dequeueReusableCellWithIdentifier: SettingsCellID forIndexPath :indexPath];// 要加上forIndexPath:参数cell必须提前注册
    // 设置 cell( 取出字典 )
    cell. dict = [ self dictWithIndexPath:indexPath];
    return cell;
}


注册cell可重用单元格时的注意点
在storyboard中已经注册了cell的可重用标识符  点击cell时 push到下一个视图控制器后  
如果 再用代码 注册一边cell的可重用单元格  会覆盖之前
// 视图被加载完成之后被调用, stroyboary 中的原型 cell ,已经存在
- (
void )viewDidLoad
{
    [
super viewDidLoad ];
   
   
// tableView 注册可重用单元格,使用 Cell 作为可重用标识符,会覆盖之前在 storyboard 中注册的原型 cell
   
// 并没有 segue 连线,所以再点击 tableViewCell ,就不会跳转了
    [
self . tableView registerClass :[ UITableViewCell class ] forCellReuseIdentifier : @"Cell" ];
}


解决方法可以在UITableView的代理方法选中某行时  
- ( void )tableView:( UITableView *)tableView didSelectRowAtIndexPath:( NSIndexPath *)indexPath;{

   
CZWebViewController * vc = [[ CZWebViewController alloc ] init ];
   
    [
self . navigationController pushViewController :vc animated : YES ];

    // 拼接文件全路径 传给目标控制器
    vc.
fullPath = [ self . fileDir stringByAppendingPathComponent : self . files [indexPath. row ]];
}


==================================================
下面是如果用stroyboard注册cell时 用下面的方法给目标控制器传值
// 用来给目标视图控制器赋值的,用 storyborad 开发
- ( void)prepareForSegue:( UIStoryboardSegue *)segue sender:( id)sender
{
    CZWebViewController *vc = segue. destinationViewController;
   
    // 1. 知道用户当前选中的行
    NSIndexPath *indexPath = [ self. tableView indexPathForSelectedRow];
    NSLog( @"%@", self. files[indexPath. row]);

    vc. fullPath = [ self. fileDir stringByAppendingPathComponent: self. files[indexPath. row]];

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值