前言:

框架对于UITableView、UITableViewCell 封装了不少功能,下面开始介绍。

1、UITableView 基本定义。

 

@interface UITableView(ST)

#pragma mark 核心扩展
typedef void(^OnAddTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^OnDelTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef void(^OnAddTableCellAction)(STUITableViewCellAction *cellAction, NSIndexPath *indexPath);
typedef void(^OnAddTableSectionHeaderView)(UIView *sectionHeaderView,NSInteger section);
typedef void(^OnAddTableSectionFooterView)(UIView *sectionFooterView,NSInteger section);

typedef void(^OnAfterTableReloadData)(UITableView *tableView);
//!用于为Table追加每一行的Cell
@property (nonatomic,copy) OnAddTableCell addCell;
//!用于为Table追加每一行的Cell的滑动菜单
@property (nonatomic,copy) OnAddTableCellAction addCellAction;
//!用于为Table追加每一组Section的标题View
@property (nonatomic,copy) OnAddTableSectionHeaderView addSectionHeaderView;
//!用于为Table追加每一组Section的Bottom View
@property (nonatomic,copy) OnAddTableSectionFooterView addSectionFooterView;
//!用于为Table移除行的Cell
@property (nonatomic,copy) OnDelTableCell delCell;
//!用于为Table reloadData 加载完数据后触发
@property (nonatomic,copy) OnAfterTableReloadData afterReload;
//!获取Table的数据源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!设置Table的数据源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;
//!存档所有Cell的高度(由系统控制)[存档格式为:section key,[row Array]]
@property (readonly,nonatomic,retain) NSMutableDictionary *heightForCells;

//!是否重用Cell(默认Yes)
-(BOOL)reuseCell;
-(BOOL)reuseCell:(BOOL)yesNo;
//!是否自动控制Table的高度
-(BOOL)autoHeight;
//!设置是否自动控制Table的高度
-(UITableView*)autoHeight:(BOOL)yesNo;
//!获取默认的UITableViewCellStyle
-(UITableViewCellStyle)cellStyle;
//!设置默认的UITableViewCellStyle
-(UITableView*)cellStyle:(UITableViewCellStyle)style;
//!获取是否允许编辑【删除】属性
-(BOOL)allowEdit;
//!设置是否允许编辑【删除】
-(UITableView*)allowEdit:(BOOL)yesNo;
//!移除数据源和数据行(并重新计算且刷新高度)
-(UITableView*)afterDelCell:(NSIndexPath*)indexPath;
#pragma mark 扩展属性
-(UITableView*)scrollEnabled:(BOOL)yesNo;
//!分组数(默认1)
-(UITableView*)sectionCount:(NSInteger)count;
//!每个Section的num数:参数可以传递:@[@"1",@"2",@"2",@"1"] 或者:@"1,2,2,1"
-(UITableView*)rowCountInSections:(id)nums;
@end

2、UITableViewCell 基本定义:

@interface UITableViewCell(ST)
//!获取当前所在的table,(weak,不能造成双strong引用)
@property (readonly,nonatomic,weak) UITableView *table;
//!获取Cell的数据源
@property (nonatomic,strong) id source;
//!Cell是否重用的Cell,如果是,就不要再添加子控制,避免重复添加。
//@property (readonly,nonatomic,assign) BOOL isReused;
//!设置Cell的数据源
-(UITableViewCell *)source:(id)dataSource;
//!创建或复用Cell
+ (instancetype)reuseCell:(UITableView *)tableView index:(NSIndexPath *)index;
//!获取Cell所在的行数
-(NSIndexPath*)indexPath;
-(UITableViewCell*)indexPath:(NSIndexPath*)indexPath;
//!获取是否允许删除属性
-(BOOL)allowDelete;
//!设置是否允许删除
-(UITableView*)allowDelete:(BOOL)yesNo;
//!数据源中的第一个字段,系统自动设置
-(NSString*)firstValue;
-(UITableViewCell*)firstValue:(NSString*)value;
//当Cell的高度在绑定后,需要动态根据子内容高度变化,再次刷新高度时使用。
-(UITableViewCell*)resetHeightCache;
#pragma mark 扩展属性
-(UITableViewCell*)accessoryType:(UITableViewCellAccessoryType)type;
-(UITableViewCell*)selectionStyle:(UITableViewCellSelectionStyle)style;

#pragma mark 扩展
//!获取Cell的滑动菜单项。
@property (nonatomic,strong) STUITableViewCellAction *action;

@end

UITableView 基本用法示例一:

[[[[[sagit addTableView:nil] autoHeight:YES]  width:610] toCenter] block:^(UITableView* table)
     {
         [table relate:TopBottom v:60 v2:60];
         [table backgroundColor:ColorClear];
         table.backgroundView=[[[[UIImageView new] image:@"answer_bg_rank"]stretch] width:1 height:1];
         table.separatorColor = [ColorWhite alpha:0.2];
         table.separatorInset=UIEdgeInsetsMake(0,26, 0, 26);
         table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath)
         {
             [cell width:1 height:140]; // 1 代表 100% <=1 被处理成百分比。
             cell.accessoryType=UITableViewCellAccessoryNone;
             cell.backgroundColor=ColorClear;
             
             
             //数据
             AnswerUserRankModel *model=[[AnswerUserRankModel new] initWithObject:cell.source];
             NSString *score=[[@(model.Score) stringValue] append:@""];
             
             [cell.contentView block:^(UIView* view)
              {
                  [view width:1 height:1];
                  if(indexPath.row!=table.source.count-1)
                  {
                      [[[[view addLine:nil color:@"#81F0D7"] width:2 height:30]y:140-15] relate:Right v:26];
                      [[[[view addLine:nil color:@"#81F0D7"] width:30 height:2] y:140] relate:Right v:26];
                  }
                  
                  [view addLabel:nil text:STNumString(model.Rank) font:30 color:ColorWhite];
                  [[STLastView x:50] toCenter:Y];
                  
                  [[[[view addImageView:nil] url:model.PhotoPath] width:80 height:80] corner:YES];
                  [[STLastView x:122] toCenter:Y];
                
                  [[[[view addLabel:nil text:model.NickName font:30 color:@"#FB8107"] onRight:STPreView x:42] toCenter:Y] width:72*2];
                  [[[view addImageView:nil img:@"answer_bg_rankscore"] width:196 height:20] block:^(UIImageView* scoreView)
                   {
                       [[scoreView x:192*2] toCenter:Y];
                       //[[scoreView relate:Right v:160] toCenter:Y];
                       [[scoreView addLabel:nil text:score font:30 color:@"#81F0D7"] toCenter];
                       //[scoreView stSizeToFit];
                   }];
                  [view onClick:^(id view)
                   {
                       [self stPush:[STNew(@"User") key:@"uid" value:model.UserID]];
                   }];
              }];
             
         };
     }];

效果:

 

 

UITableView 基本用法示例二:

 [[[[sagit addTableView:@"tableView" style:UITableViewStyleGrouped] autoHeight:YES] onBottom:STPreView y:20]  block:nil on:^(UITableView* table) {
        [table reuseCell:NO];
        table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath)
        {
            NSString *name=cell.source[@"name"];
            NSString *title=cell.source[@"title"];
            NSString *holder=cell.source[@"holder"];
            if(holder==nil){holder=title;}
            NSString *pick=cell.source[@"pick"];
            NSString *maxLength=cell.source[@"maxLength"];
            
            [[[cell.contentView addLabel:nil text:title font:30] relate:Left v:50] toCenter:Y];//label是固定的。
            UIView *textView;
            
            if([title isEqualToString:@"简介"])
            {
                textView=[[[[[cell.contentView addTextView:name placeholder:holder font:30] maxRow:3] maxLength:100]
                          textAlignment:NSTextAlignmentLeft] height:0.8];
                UIEdgeInsets inset=textView.asTextView.textContainerInset;
                inset.left-=5;
                textView.asTextView.textContainerInset=inset;
            }
            else
            {
                textView=[[cell.contentView addTextField:name placeholder:holder font:30] height:0.8];
                if(maxLength!=nil)
                {
                    [STLastTextField maxLength:[maxLength integerValue]];
                }
            }
            [[[textView onRight:STPreView x:50] relate:Right v:0] toCenter:Y];
            
            if(pick==nil)
            {
                cell.accessoryType=UITableViewCellAccessoryNone;
            }
            else
            {
                [[STLastView addClick:@"pick"] key:@"pick" value:pick];
            }
        };
        table.afterReload = ^(UITableView *tableView)
        {
            if(!self.hasLoaded)
            {
                self.hasLoaded=YES;
                [self setToAll:Sagit.Global.User.user];
            }
        };
        
    }];

效果:

 

数据源设置:

-(void)initData
{
    [super initData];//加载子UI的数据。
    UITableView *table=STFirstTable;
    table.source=@[@{@"title":@"姓名",@"name":@"NickName",@"maxLength":@"15"},
                   @{@"title":@"简介",@"name":@"Description",@"holder":@"请简单介绍一下自己!"},
                   @{@"title":@"公司",@"name":@"Company",@"holder":@"所在公司!",@"maxLength":@"20"},
                   @{@"title":@"年龄",@"name":@"Age",@"pick":@"年龄"},
                   @{@"title":@"学历",@"name":@"Edu",@"pick":@"学历"},
                   @{@"title":@"身高",@"name":@"Height",@"pick":@"身高"},
                   @{@"title":@"星座",@"name":@"Constellation",@"pick":@"星座"},
                   @{@"title":@"婚姻",@"name":@"MarrStatus",@"pick":@"婚姻"},
                   @{@"title":@"职业",@"name":@"Profession",@"pick":@"职业"},
                   @{@"title":@"收入",@"name":@"Wages",@"pick":@"月薪"}];
    
    [[table sectionCount:2] rowCountInSections:@"3,7"];
    //table.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,1, 0.01f)];
    table.sectionFooterHeight=0.2;
    // table.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,1, 1.0f)];
    //self.automaticallyAdjustsScrollViewInsets = NO;
    [table reloadData];
    
}

 

UITableView 基本用法示例三:循环嵌套[2021-11-11更新]

-(void)initUI
{
    [[[[sagit addTableView:nil]relate:TopBottom v:100 v2:200] backgroundColor:ColorRed] block:^(UITableView* table) {
        table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
            [cell backgroundColor:ColorGreen];
            [[cell addLabel:nil text:cell.firstValue] toCenter];
            [[[cell addSwitch:nil on:NO] onSwitch:^(UISwitch *view) {
                if(view.on)
                {
                    [self addTable:cell];
                }
                else
                {
                    [cell.lastSubView removeFromSuperview];
                    [cell refleshTableHeight];
                }
               
            }] relate:Right v:50];

        };
        table.source=@[@{@"a":@"aa"},@{@"a":@"bb"},@{@"a":@"cc"}];
        }];
}
-(void)addTable:(UITableViewCell*)cell
{
                    [[[[cell addTableView:nil] autoHeight:YES]  backgroundColor:ColorBlack] block:^(UITableView* cellTable) {
                        [[cellTable onBottom:cell.lastSubView.preView] x:0];
                        cellTable.addCell = ^(UITableViewCell *childCell, NSIndexPath *indexPath) {
                            childCell.accessoryType=UITableViewCellAccessoryNone;
                            [[childCell backgroundColor:ColorRandom] width:1 height:100];
                            NSString * value=childCell.firstValue;
                            [[childCell addLabel:nil text:value] toCenter];
                        };
                        cellTable.afterReload = ^(UITableView *tableView) {
                            [cell refleshTableHeight];
                           
                        };
                        cellTable.source=@[@{@"b":@"aaaa"},@{@"b":@"bb"},@{@"b":@"cc"}];
                    }];
}

代码细节说明:

Table循环嵌套时,由于表格加载,有延后时,所以,需要在子表格的afterReolad事件(即加载完后)处理。

单元格新增了:refleshTableHeight:刷新表格高度。该方法仅会刷新单元格和表格的高度(不触发table的reload事件)。

循环效果图:

 

 

 

UICollectionView、UICollectionViewCell 基本定义

@interface UICollectionView(ST)
#pragma mark 核心扩展
typedef void(^AddCollectionCell)(UICollectionViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^DelCollectionCell)(UICollectionViewCell *cell,NSIndexPath *indexPath);
//!用于为Table追加每一行的Cell
@property (nonatomic,copy) AddCollectionCell addCell;
//!用于为Table移除行的Cell
@property (nonatomic,copy) DelCollectionCell delCell;
//!获取Table的数据源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!设置Table的数据源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;
@end

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

@interface UICollectionViewCell(ST)
//!获取Cell的数据源
@property (nonatomic,strong) NSMutableDictionary<NSString*,id> *source;
//!设置Cell的数据源
-(UICollectionViewCell *)source:(NSMutableDictionary<NSString*,id> *)dataSource;
//!创建或复用Cell
+ (instancetype)reuseCell:(UICollectionView *)tableView index:(NSIndexPath *)index;
//!获取当前所在的table
-(UICollectionView*)table;

//!获取是否允许删除属性
//-(BOOL)allowDelete;
//!设置是否允许删除
//-(UITableView*)allowDelete:(BOOL)yesNo;
//!数据源中的第一个字段,系统自动设置
-(NSString*)firstValue;
-(UICollectionViewCell*)firstValue:(NSString*)value;
@end

 

这两个和上面两个的用法基本一致,功能比上面的还少,就不过多介绍了。

3、左滑菜单说明

如果左滑的菜单只有删除,那么只需要设置:

[table allowEdit:YES]

删除点击的事件:

table.delCell = ^BOOL(UITableViewCell *cell, NSIndexPath *indexPath)
    {
        [Sagit.RongYun removeFromBlacklist:cell.firstValue success:^{
            [this.http get:UrlSetBlacklist paras:@{@"blackUserID":cell.firstValue, @"blackFlag":@"2"} success:^(STHttpModel *result) {
                if (result.success)
                {
                    [cell.table afterDelCell:indexPath];
                }
            } ];
        } error:^(RCErrorCode status) {

        }];

        return false;
    };

默认是处理完业务,return true;(之后框架会调用 afterDelCell 移除行并重绘高度)。

如果有异步操作,也可以先return false; 再根据结果自己调用 afterDelCell 方法。

如果涉及到添加多个菜单:

原生事件:

-(NSArray<UITableViewRowAction*>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
    RCConversationModel *model = self.conversationListDataSource[indexPath.row];
    UITableViewRowAction *del  = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"删除" handler:^(UITableViewRowAction * _Nonnull action,NSIndexPath * _Nonnull indexPath) {
    ......
    }];
    
    UITableViewRowAction *top  = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"置顶" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
       ......
    }];
    top.backgroundColor        = STColor(@"#fe9d00");
    return @[del, top];
}

框架用法 [2020-09-17更新]

 table.addCellAction = ^(STUITableViewCellAction *actions, NSIndexPath *indexPath) {
            [actions addAction:@"置顶" bgColor:ColorRed onAction:nil];
            [actions addAction:@"删除2" bgColor:ColorBlack onAction:^(UITableViewCell *cell, NSIndexPath *indexPath) {
                //点击事件。
            }];
        };

结果图:

如果需要自定义滑动菜单:

【原生的方法:可以改变样式,但改变不了坐标,所以在原生的基础上添加自己的视图即可】

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    
        UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
        if(cell!=nil)
        {
            UIView *uiSwipeActionPullView=cell.superview.subviews[0]; //UISwipeActionPullView
            if([uiSwipeActionPullView isKindOfClass:[UITableViewCell class]])
            {
                //IOS 13 以下。
                for (UIView *view in tableView.subviews) {
                    if([view isKindOfClass:NSClassFromString(@"UISwipeActionPullView")])
                    {
                        uiSwipeActionPullView=view;
                        break;
                    }
                }
            }
            //uiSwipeActionPullView=>UISwipeActionStandardButton => UIView,UIButtonLabel
            for (UIView * btnView in uiSwipeActionPullView.subviews) {
                [btnView backgroundColor:STDeviceColor];
                [btnView removeAllSubViews];
                [[[[[[btnView addButton:nil title:@"click" font:24 color:ColorGreen img:nil] width:120 height:0.8] layerCornerRadius:24]
                   toCenter:Y] backgroundColor:ColorBlue] x:20];
            }
        }
}

滑动后的布级层级:(IOS 13) 【IOS13以下的View层级是在UITableView下

框架用法 [2020-09-17更新] 

 table.addCellAction = ^(STUITableViewCellAction *actions, NSIndexPath *indexPath) {
            [actions addAction:^(UIView *cellSwipeView, NSIndexPath *indexPath) {
                [[[[[[cellSwipeView addButton:nil title:@"click" font:24 color:ColorGreen img:nil] width:120 height:0.8] layerCornerRadius:24]
                   toCenter:Y] backgroundColor:ColorBlue] x:20];
            } onAction:nil];
        };

效果图:

 

PS:addAction 有两个重载方法,一个用于原生的文字和背景色调整;另一个用于自定样式。

4、分区标题

原生用法:

// 设置表头的高度。如果使用自定义表头,该方法必须要实现,否则自定义表头无法执行,也不会报错
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 80*Ypt;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

{

    UIView *view=[[[UIView new] width:1 height:80] backgroundColor:[ColorBlue alpha:0.5]];
    [[[view addLabel:nil text:@"title"] toCenter] sizeToFit];
    [[view stSizeToFit] layerCornerRadius:20 byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight];
 
    return view;
}

框架用法: [2021-11-11更新]

table.addSectionHeaderView = ^(UIView *sectionView, NSInteger section) {
            [sectionView backgroundColor:[ColorBlue alpha:0.5]];
            [[[sectionView addLabel:nil text:@"title"] toCenter] sizeToFit];
            [[sectionView stSizeToFit] layerCornerRadius:20 byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight];
        };

结果图片:

 

posted on 2020-08-15 16:50  路过秋天  阅读(757)  评论(0编辑  收藏  举报
路过秋天