平時用的也就幾個屬性和幾個方法,但是API又臭又長,今天整理一下。
一般使用
// 1 先創建tableView
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
/*
typedef NS_ENUM(NSInteger, UITableViewStyle) {
UITableViewStylePlain, // 平鋪式(補充:有section時,自動懸浮在頂部)
UITableViewStyleGrouped // 分段式
};
*/
_tableView.delegate = self;
_tableView.dataSource = self;
// 設置 默認高度,對應有高度估算,但是一般用第三方,高度緩存比較好用。
_tableView.rowHeight = 60;// 也可以在 代理中設置,高度固定的話推薦這里設置。
// 注冊使用的 cell類,自己寫的也一樣
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:NSStringFromClass([UITableViewCell class])];
// 2 實現必要的幾個代理與數據源
// 必須
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;// 每段數量,一般結合數組使用
}
// 必須 cell初始化
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 已注冊的使用下面一行代碼即可,不需要判斷 !cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([UITableViewCell class])];
cell.textLabel.text = [NSString stringWithFormat:@"%zi",indexPath.row];
// more setting
return cell;
}
// 可選 分段數量
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;// 分段式特有,默認為1 。
}
// 可選 cell 高度,對應一個 估算高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 66;
}
// 事件 已選中 與 已反選中
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// do 這個比較多,下面基本沒怎么用過
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
// do
}
// 別忘了,簡單粗暴的 更新數據源
[_tableView reloadData];
到這里,tableView 基本使用過關。再加上自定義cell 的話,基本上的頁面也差不多都能畫個草圖了(不考慮細節)
額外屬性
// 分割線設置
_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;// 分割線
_tableView.separatorColor = [UIColor redColor];
_tableView.separatorInset = UIEdgeInsetsMake(0, 44, 0, 0);
// iOS8 分割線 毛玻璃效果
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
_tableView.separatorEffect = vibrancyEffect;
// iOS9 根據內容調整寬度,不設置可能會出現iOS9 cell顯示異常
_tableView.cellLayoutMarginsFollowReadableWidth = NO;
_tableView.allowsSelection = YES;// cell 是否可以選擇
_tableView.allowsSelectionDuringEditing = YES;// 編輯模式是否可以選擇 cell
_tableView.allowsMultipleSelection = YES;// 是否可以多
_tableView.allowsMultipleSelectionDuringEditing = YES;// 編輯模式是否可以多選(YES 是會使默認的 刪除和插入編輯模式失效)
添加額外的 View - head/foot/background
- tableView 本身的 background
// 背景,一般設置后,需要設置cell 透明(cell.contentView 與 cell 本身),展示這個背景
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
// do custom:
_tableView.backgroundView = backgroundView;
- tableView 本身的 tableHead / tableFoot
// 一個tableView 就一對,是跟隨表上下移動,與section 的不一樣!
UIView *tableHeadView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 44)];
// do custom,使用自動布局的話,建議在tableHeadView 鋪底的基礎上addSubView:(直接加可能會異常)
_tableView.tableHeaderView = tableHeadView;
UIView *tableFootView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 66)];
// do custom
_tableView.tableFooterView = tableFootView;
- section 的 head / foot
// 系統默認,可以設置高度
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return @"header";
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return @"footer";
}
// 自定義
// 與cell 同理注冊(同時注冊了head/foot)
[_tableView registerClass:[UIView class] forHeaderFooterViewReuseIdentifier:NSStringFromClass([UIView class])];
// 默認高度:每個section 一樣,不一樣用代理設置
_tableView.sectionHeaderHeight = 40;
_tableView.sectionFooterHeight = 40;
// 代理
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 40;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 40;
}
// 設置 headView 和FootView 會使上面title 和 height 失效。
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
headView.backgroundColor = [UIColor yellowColor];
return headView;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView *footView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
footView.backgroundColor = [UIColor orangeColor];
return footView;
}
高亮 選中 與 滾動
- 高亮代理
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%zi",indexPath.row);
}
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath {
}
- 2 設置選中
//
[_tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:1] animated:YES scrollPosition:UITableViewScrollPositionTop];
/*
typedef NS_ENUM(NSInteger, UITableViewScrollPosition) {
UITableViewScrollPositionNone,
UITableViewScrollPositionTop,
UITableViewScrollPositionMiddle,
UITableViewScrollPositionBottom
};// 選中cell 滾動到的位置
*/
[_tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:1] animated:YES];
- 3 設置滾動
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:2] atScrollPosition:UITableViewScrollPositionTop animated:YES];
[_tableView scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionTop animated:YES];
增刪改移
- 必須結構
關鍵是對應修改數據源
[tableView beginUpdates];
// 使用 增刪改移(之前必須先修改對應的數據源,可以在begin 之前)
[tableView endUpdates];
- 增
[tableView beginUpdates];
[self.tableSource insertObject:@"test" atIndex:3];
[tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:3 inSection:0]] withRowAnimation:UITableViewRowAnimationLeft];
/*
typedef NS_ENUM(NSInteger, UITableViewRowAnimation) {
UITableViewRowAnimationFade,
UITableViewRowAnimationRight, // slide in from right (or out to right)
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
}; // 過渡動畫效果
*/
[tableView endUpdates];
- 刪
//
[tableView beginUpdates];
[self.tableSource removeObjectAtIndex:3];
[tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:3 inSection:0]] withRowAnimation:UITableViewRowAnimationLeft];
[tableView endUpdates];
- 改
//
[tableView beginUpdates];
[self.tableSource replaceObjectAtIndex:3 withObject:@"replace"];
[tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:3 inSection:0]] withRowAnimation:UITableViewRowAnimationLeft];
[tableView endUpdates];
- 移
//
[tableView beginUpdates];
[self.tableSource exchangeObjectAtIndex:2 withObjectAtIndex:3];
[tableView moveRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
[tableView endUpdates];
- 下面的請告訴我怎么用,原理應該跟上面的一樣,但是試了幾次沒成功,阿西吧。
- (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);
編輯 - 就是插入 與 刪除 - 系統提供樣式
- 默認模式 - 刪除 插入
// 是否可以編輯
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
// 編輯方式 插入 和 刪除
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
/*
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) {
UITableViewCellEditingStyleNone,(移動專用)
UITableViewCellEditingStyleDelete,(刪除專用)
UITableViewCellEditingStyleInsert(插入專用)
};
*/
}
// 是否縮進,(設置NO 是為了下面移動使用)這里必須YES
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
// 刪除樣式的時候,顯示的提示
- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED {
return @"雅蠛蝶";
}
// iOS8
//- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED {
// return @[];
//}
// 將要
- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
// do
}
// 完成
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {
// do
}
// 觸發事件
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// 點擊事件,1:默認刪除,需要點擊左滑出現的刪除才觸發。2:插入,點擊+即觸發
// 根據實際 情況刪除 或者 插入,上面講過了
[tableView beginUpdates];
[self.tableSource removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
}
- 編輯 之 多選
_tableView.allowsMultipleSelectionDuringEditing = YES;// 編輯模式是否可以多選(YES 是會使上面默認的 刪除和插入編輯模式失效)
// 單選時 選中的行
NSIndexPath *singleSelect = self.tableView.indexPathForSelectedRow;
// 多選時選中的行s,
NSArray *selects = self.tableView.indexPathsForSelectedRows;
// to do 根據 上面的 NSIndexPath 可以進行相應的 刪除等操作。
編輯 之 移動
- (UITableViewCellEditingStyle )tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
// cell 位置 移動了,但是數據源沒變,需要手動調整
[self.tableSource exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row];
NSLog(@"%@",self.tableSource[sourceIndexPath.row]);
NSLog(@"%@",self.tableSource[destinationIndexPath.row]);
NSLog(@"%@",self.tableSource);
}
索引
_tableView.sectionIndexMinimumDisplayRowCount = 12;// 索引相關
_tableView.sectionIndexColor = [UIColor redColor]; // 索引字顏色
_tableView.sectionIndexBackgroundColor = [UIColor yellowColor];// normal 背景色
_tableView.sectionIndexTrackingBackgroundColor = [UIColor blueColor];// highlighted 背景色
[_tableView reloadSectionIndexTitles];
// 索引內容
- (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return @[@"0",@"1",@"2",@"3",@"4",@"5",@"6"];// 自己寫
return UITableViewIndexSearch;// 默認 section 第一個
}
// 點擊索引 返回滾動 section 位置
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index __TVOS_PROHIBITED {
NSLog(@"索引內容:%@ - 索引index:%zi",title,index);
// do
return index;
}
復制粘貼
直接舉例
// 是否 顯示 菜單
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
// 顯示哪些 操作
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender {
if (action == @selector(cut:)){
return YES;
} else if(action == @selector(copy:)){
return YES;
} else if(action == @selector(paste:)){
return YES;
} else if(action == @selector(select:)){
return NO;
} else if(action == @selector(selectAll:)){
return NO;
} else {
return NO;
}
}
// 點擊 回調 對應操作
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender {
if (action ==@selector(copy:)) {
[UIPasteboard generalPasteboard].string = self.tableSource[indexPath.row];
}
if (action ==@selector(cut:)) {
[UIPasteboard generalPasteboard].string = self.tableSource[indexPath.row];
[self.tableSource replaceObjectAtIndex:indexPath.row withObject:@""];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
}
if (action ==@selector(paste:)) {
NSString *pasteString = [UIPasteboard generalPasteboard].string;
[self.tableSource replaceObjectAtIndex:indexPath.row withObject:pasteString];
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
}
}
展示相關 - 再設置犀利自定義時用的比較多
例如,section headView 將要消失時,頂在最上面不消失,反之亦然。
- (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);
// 實際代碼,不太好舉例。
獲取信息
// UITableView.h 200-218 行,不寫了
其他
// 修改選中/反選項 不是很常用
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:indexPath.section];
}
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section + 1];
}
// 縮進級別 不是像素
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
return 12;
}
待補充
// iOS9 屬性
@property (nonatomic) BOOL remembersLastFocusedIndexPath NS_AVAILABLE_IOS(9_0);
@property (nonatomic, strong, readonly, nullable) NSIndexPath *previouslyFocusedIndexPath;
@property (nonatomic, strong, readonly, nullable) NSIndexPath *nextFocusedIndexPath;
// iOS9 代理
- (BOOL)tableView:(UITableView *)tableView canFocusRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
- (BOOL)tableView:(UITableView *)tableView shouldUpdateFocusInContext:(UITableViewFocusUpdateContext *)context NS_AVAILABLE_IOS(9_0);
- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator NS_AVAILABLE_IOS(9_0);
- (nullable NSIndexPath *)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView NS_AVAILABLE_IOS(9_0);
// 其他代理
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath;
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
// iOS 8
typedef NS_ENUM(NSInteger, UITableViewRowActionStyle) {
UITableViewRowActionStyleDefault = 0,
UITableViewRowActionStyleDestructive = UITableViewRowActionStyleDefault,
UITableViewRowActionStyleNormal
} NS_ENUM_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED;
NS_CLASS_AVAILABLE_IOS(8_0) __TVOS_PROHIBITED @interface UITableViewRowAction : NSObject <NSCopying>
+ (instancetype)rowActionWithStyle:(UITableViewRowActionStyle)style title:(nullable NSString *)title handler:(void (^)(UITableViewRowAction *action, NSIndexPath *indexPath))handler;
@property (nonatomic, readonly) UITableViewRowActionStyle style;
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) UIColor *backgroundColor; // default background color is dependent on style
@property (nonatomic, copy, nullable) UIVisualEffect* backgroundEffect;
@end
// 其他
UIKIT_EXTERN NSString *const UITableViewIndexSearch NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED;
UIKIT_EXTERN const CGFloat UITableViewAutomaticDimension NS_AVAILABLE_IOS(5_0);
UIKIT_EXTERN NSString *const UITableViewSelectionDidChangeNotification;
1