参考:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html
简介:
--一个@的实例意味着展示和编辑分层列表的信息。一个tableview在一栏中展示了一系列item,它是UIScrollview的子类,允许用户在列表上滑动,但只能是垂直方向。
--tableview有俩种样式,见下图:
Datasource
@required
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional
// Default is 1 if not implemented
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; //每个section的title
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; //每个section的footer
// Editing/Moving or Reordering
// 不同的row可以有同的-editing属性。当row的editing属性为NO,则它不可编辑(tableview setEditing改变的时候它没影响);为YES时,可编辑,可以有不同的editingStyle,详见"editingStyleForRowAtIndexPath方法"。Default is YES;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
// 不同的row是否可以移动。当tableview处于editing状态时:如果某个row返回值为NO,则它的reorder accessory view不会显示,不可移动;如果某个row的返回值为YES的时候,且datasource有实现-tableView:moveRowAtIndexPath:toIndexPath:方法,则显示该row的reorder accessory view 可以移动,否则还是不显示reorder accessory view,不可移动;
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
// Index
//返回list of section titles to display in section index view (e.g. "ABCD...Z#")
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
// which section corresponds to sectionIndexTitle,当点击某个sectionIndexTitle时候,返回某个section的值,tableview就移动到该section;
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index;
// Data manipulation - insert and delete / reorder or moving support
// 当tableview处于editing状态时,如果row可编辑,则会has the minus or plus button invoked(based on the UITableViewCellEditingStyle for the cell)。当点击minus or plus button的时候,就会调用该方法(如果是minus button,需要点击到随后的delete才会触发方法);
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
// 当tableview处于editing状态,并且row可以canMove,如果拖动某row换行,则调用改方法;
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
@end
delegate方法
@optional
// Display customization
- (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);
- (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);
// Variable height support
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
// tableview在每次reload data时都会要所有cell的高度,这非常影响程序性能,使用estimatedHeight methods to quickly calcuate guessed values 去快速加载tableview
// 原理:If these methods are implemented, the above -tableView:heightForXXX calls will be deferred until views are ready to be displayed, so more expensive logic can be placed there.
- (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);
// Section header & footer information.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; //custom view for header. will be adjusted to default or specified header height
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; //custom view for footer. will be adjusted to default or specified footer height
// Accessories (disclosures).
// 当cell的accessaryType为UITableViewCellAccessoryDetailDisclosureButton时,点击accessaryView将会调用delegate的tableView:accessoryButtonTappedForRowWithIndexPath方法。否则只是didSelectRowAtIndexPath;
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath NS_DEPRECATED_IOS(2_0, 3_0);
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
// Selection
// -tableView:shouldHighlightRowAtIndexPath: is called when a touch comes down on a row.
// Returning NO or YES 当前选中的row是否高亮
- (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);
// Called before the user changes the selection. Return a new indexPath, or nil, to change the proposed selection.
/* 先点击row1,再点击row2,俩着执行顺序:在下一行将要选中后才取消上一行的选中
willSelectRowAtIndexPath 当前row为:0
didSelectRowAtIndexPath 当前row为:0
willSelectRowAtIndexPath 当前row为:1
willDeselectRowAtIndexPath 当前row为:0
didDeselectRowAtIndexPath 当前row为:0
didSelectRowAtIndexPath 当前row为:1
*/
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// Called after the user changes the selection.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// Editing
// 允许cell自定义editingStyle.Default is UITableViewCellEditingStyleDelete(when the table has editing property set to YES)
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
// 当tableview editing为YES,点击minus时出来deleteButton的title.Default is 'Delete';
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0);
// 当tableview处于编辑时,控制row的background是否is indented就是row所在的那个框,例如缩不缩进可能会导致左边的edit按钮是在row框里面or外面)。Default is YES.(方法仅仅适用于grouped style 且跟之后的indentation level 方法没有关系)
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// 方法被调whenever the 'editing' property is automatically changed by the table (allowing insert/delete/move). 注意,如果是tableview的'editing'改变,方法不会调用。只有This is done by a swipe activating a single row。
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
// Moving/reordering
// Allows customization of the target row for a particular row as it is being moved/reordered
// 注意区别之前的tableView:moveRowAtIndexPath:toIndexPath方法。当手指按住reorder accessory view移动时,只要有row moved/reordered都会调用该方法,而前者方法只有当手指放开reorder accessory view时,结束move/order操作才会调用它。返回值代表进行移动操作后回到的行,如果设置为当前行,则不论怎么移动都会回到当前行。
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;
// Indentation
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath; //不同row的缩进
// 长按出来的Copy/Paste操作
- (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
dataSource/delegate方法大概执行顺序(所有方法均实现):
numberOfSectionsInTableView;
有多少section,例如k;tableView:estimatedHeightForHeaderInSection+ tableView:estimatedHeightForFooterInSection;
计算k-1 section
的header
、footer
大概高度tableView:numberOfRowsInSection;
k-1 section
有多少row
tableView:estimatedHeightForRowAtIndexPath
计算k-1 section
中所有row
的大概高度;重复1)~4)步骤,直到所有0至k-1的
section
计算完;sectionIndexTitlesForTableView
索引titles
;`tableView:heightForRowAtIndexPath;依次计算visible区域(屏幕区域)里每个cell的高度(这里的所有cell记做集合A,决定于屏幕高度和estimatedHeightForXXX方法)
tableView:cellForRowAtIndexPath
创建第一个indexPath上的celltableView:indentationLevelForRowAtIndexPath
indexPath
上的cell的缩进;tableView:canEditRowAtIndexPath
indexPath
上的cell编辑属性;tableView:willDisplayCell:forRowAtIndexPath
indexPath
上的cell将要显示;重复8)~11),直到所有
visible
区域cell
(集合A)创建完毕;tableView:heightForHeaderInSection + tableView:heightForFooterInSection + tableView:viewForHeaderInSection + tableView:viewForHeaderInSection
依次计算visible
区域里所有section 的header高度、footer高度、viewForHead、viewForFooter;
执行顺序(没有实现estimatedHeight
这些方法):
-
numberOfSectionsInTableView
;有多少section,例如k; -
tableView:heightForHeaderInSection + tableView:heightForFooterInSection
计算k-1 section的header、footer高度; -
tableView:numberOfRowsInSection
k-1 section
有多少 row; - .tableView:heightForRowAtIndexPath;计算k-1 section中所有row得高度;
- 重复1)~4)步骤,直到所有0至k-1的section计算完
-
sectionIndexTitlesForTableView
索引titles; -
tableView:cellForRowAtIndexPath
创建第一个indexPath
上的cell -
tableView:indentationLevelForRowAtIndexPath
indexPath
上的cell的缩进; -
tableView:canEditRowAtIndexPath
indexPath
上的cell编辑属性; -
tableView:willDisplayCell:forRowAtIndexPath
indexPath
上的cell将要显示; - 重复7)~12),知道所有visible区域(屏幕)cell创建完毕;
-
tableView:viewForHeaderInSection + tableView:viewForHeaderInSection
依次计算visible
区域里所有的viewForHead、viewForFooter;
备注:
1.由上可看出,estimatedHeight
在加载tableview的时候代替了heightFor方法,heightFor方法只有当cell需要显示的时候,才会调用。
2.关于estimatedHeightForXXX
相关方法,里面的返回值并不能随意填写的,应该是真实高度的大概值;因为在加载tableview的时候,当所有的section header/footer row的高度都大概计算完,开始计算高度、并创建visible区域的cell时候,这些cell属不属于visible区域的判断依据就是之前的estimatedHeightForXXX
方法返回的值算出来的;例如estimatedHeightForXXX相关方法返回值过大,算出来当前visible(屏幕)区域,包含3个section header 、footer以及里面的row,所以实际创建的时候也是创建这些cell(参考上文中方法执行顺序),当这些cell创建完,实际情况高度(heightForXXX方法所得)可能只占visible(屏幕)区域的一半,导致屏幕另一半空白。注意visible区域初始显示的cell是由estimatedHeightForXXX相关方法决定的,而不是heightForXXX这些方法真实高度决定的,所以有时tableview中visible区域尾部cell显示不出来或者创建的cell比visible区域cell多,都是estimatedHeightForXXX和heightForXXX方法相差导致的原因。
3.以上方法和ViewController那些方法关系:先执行viewdidload、willAppear等相关方法,再执行numberOfSectionsInTableView系列方法。
属性、方法
@属性 CGFloat rowHeight;sectionHeaderHeight;sectionFooterHeight; //类似相应方法,只不过是个统一值
@属性 CGFloat estimatedRowHeight; estimatedSectionHeaderHeight;estimatedSectionFooterHeight NS_AVAILABLE_IOS(7_0); //类似相应方法,只不过是个统一值
@属性 UIView *backgroundView ; //the background view will be automatically resized to track the size of the table view.
@属性 UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) ; //allows customization of the frame of cell separators 测试发现仅UIEdgeInsets中的right、left起作用
// Data
- (void)reloadData; // reloads everything from scratch. redisplays visible rows. because we only keep info about visible rows, this is cheap. will adjust offset if table shrinks
- (void)reloadSectionIndexTitles NS_AVAILABLE_IOS(3_0); // reloads the index bar.
// Info
- (NSInteger)numberOfSections;
- (NSInteger)numberOfRowsInSection:(NSInteger)section;
- (CGRect)rectForSection:(NSInteger)section; // includes header, footer and all rows
- (CGRect)rectForHeaderInSection:(NSInteger)section;
- (CGRect)rectForFooterInSection:(NSInteger)section;
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point; // returns nil if point is outside of any row in the table
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell; // returns nil if cell is not visible
- (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
- (NSArray *)visibleCells;
- (NSArray *)indexPathsForVisibleRows;
- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
- (UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);
// 滚动row identified by index path到特殊位置
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
// 滚动table使得selected row nearest to a specified position
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
// Row insertion/deletion/reloading.
// 这两个方法,是配合起来使用的,标记了一个tableView的动画块。分别代表动画的开始开始和结束。两者成对出现,可以嵌套使用。一般,在添加,删除,选择tableView中使用,并实现动画效果。在动画块内,不建议使用reloadData方法,如果使用,会影响动画。
- (void)beginUpdates; // allow multiple insert/delete of rows and sections to be animated simultaneously.
- (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.
- (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);
// Editing. When set, rows show insert/delete/reorder controls based on data source queries
@property(nonatomic,getter=isEditing) BOOL editing; // default is NO. setting is not animated.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
@属性 BOOL allowsSelection;allowsSelectionDuringEditing; allowsMultipleSelection;allowsMultipleSelectionDuringEditing;
// Selection
- (NSIndexPath *)indexPathForSelectedRow; // returns nil or index path representing section and row of selection.
- (NSArray *)indexPathsForSelectedRows NS_AVAILABLE_IOS(5_0); // returns nil or a set of index paths representing the sections and rows of the selection.
// Selects and deselects rows. These methods will not call the delegate methods (-tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath:), nor will it send out a notification.
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition;
- (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;
// Appearance
@属性 NSInteger sectionIndexMinimumDisplayRowCount;//当tableView中多少行的时候开始显示IndexList,默认的设置是NSIntegerMax,即默认是不显示indexList的
@属性 UIColor *sectionIndexColor; sectionIndexBackgroundColor; sectionIndexTrackingBackgroundColor;
@property(nonatomic) UITableViewCellSeparatorStyle separatorStyle; // default is UITableViewCellSeparatorStyleSingleLine
@property(nonatomic,retain) UIColor *separatorColor; // default is the standard separator gray
@property(nonatomic,retain) UIView *tableHeaderView; tableFooterView;
//Reusable 重用
/*
A:UITableView头文件,会找到NSMutableArray* visiableCells,和NSMutableDictnery* reusableTableCells两个结构。visiableCells内保存当前显示的cells,reusableTableCells保存可重用的cells;
B:TableView显示之初,reusableTableCells为空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。开始的cell都是通过[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]来创建,而且cellForRowAtIndexPath只是调用最大显示cell数的次数;
例如:有100条数据,iPhone一屏最多显示10个cell。程序最开始显示TableView的情况是:
1. 用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]创建10次cell,并给cell指定同样的重用标识(当然,可以为不同显示类型的cell指定不同的标识)。并且10个cell全部都加入到visiableCells数组,reusableTableCells为空。
2. 向下拖动tableView,当cell1完全移出屏幕,并且cell11(它也是alloc出来的,原因同上)完全显示出来的时候。cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。
3. 接着向下拖动tableView,因为reusableTableCells中已经有值,所以,当需要显示新的cell,cellForRowAtIndexPath再次被调用的时候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1移出reusableTableCells(测试发现cell1会被移出,而不是还留在reusableTableCells中复用);cell2移出visiableCells,cell2加入到reusableTableCells。之后再需要显示的Cell就可以正常重用了。
*/
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier; // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); // newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered
- (id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); // like dequeueReusableCellWithIdentifier:, but for headers/footers
// Beginning in iOS 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.
- (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);
关于:俩种dequeueReusableCellWithIdentifier 方法的区别:
1.一个6.0才能使用的方法;
2.使用6.0新方法的前提是,必须使用配套的register 相关方法,例如:
[_tableView registerClass:[MXCustomCell class] forCellReuseIdentifier:CellIdentifier];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:self.notNib_tableView];
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:@"6.0方法 %d", indexPath.row];
return cell;
}
3.用处:to dequeue your cell, it will be the right size and you'll be able to do layout inside your cell's contentView
备注:
参考:http://blog.sina.com.cn/s/blog_6fd90b5b0101705h.html
1.tableview 中cell的reordering示意图:
2.tableview中 cell的delete & insert操作示意图:
注:
在tableview执行deleteRow/insertRow类似操作时,tableview界面更新时,并没有reloadData,而是:
a.estimatedHeightFor每个section的header、footer、row;
b.计算visible区域每个cell的heightForRowAtIndexPath;
c.新添加的/新进入visible区域(删除)cell的cellForRowAtIndexPath方法;以及cell的indentationLevel、canEdit、canMove、editStyle、willDisplay等方法;
d.heightFor剩下/其余的row、section的header、footer;(c和d的顺序不同情况可能会调换)
3.批量插入,删除,部分更新操作:UITableView提供了一个批量操作的特性,这个功能在一次进行多个row或者scetion的删除,插入,获取更新多个cell内容的时候特别好用。所有的批量操作需要包含在beginUpdates和endUpdates块中,否则会出现异常。操作顺序如下图:
注意: 在批量操作时,不管代码中先写的添加操作还是删除操作,添加操作都会被推出执行,直到这个块中所有的删除操作都执行完以后,才会执行添加操作。如上图:首先删除section 0中的row 1,然后删除section 1,再向section 1中添加一行。执行完批量更新以后就得到右半边的结果。
4.reloadData的执行过程:跟tableview第一次加载执行过程一样(参考上文"方法执行顺序"),只不过它将所有visible区域的cell都放入reusableTableCells中,所以dequeueReusableCellWithIdentifier方法可重用cell。