iOS开发-开源类库iOS开发iOS

iOS封装到极致好用的tableView

2019-03-28  本文已影响571人  wmz啊

UITableView基本上是使用最多的一个控件,今天介绍封装后的 WMZTableView 省去写代理的时间


先直接上代码

 GroupTableView()
 .wAutoCell(YES)
 .wMasonryConfig(self.view, ^(MASConstraintMaker *make) {
     make.edges.mas_equalTo(0);
 }, self.modelArr)
 .wStart();
6af89bc8gw1f8ou1e50bzg201w01wdfr.gif

不需要写cell,是不是简化了不少,比起写那么多的代理方法,最精简的可以只传frame和data即可。

效果图是我随便写的几个自定义的cell,别介意。


Untitled.gif

用法

可以看demo了解基本都很简单清晰
1 如果要在UITableViewCell里自己写样式 需调用wDealCell,大概如下

.wDealCell(^UITableViewCell *(NSIndexPath *indexPath, UITableView *tableView,id model) {
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([UITableViewCell class])];
       if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([UITableViewCell class])];
       }
       cell.textLabel.text = model;
       return cell;
 })

2 如果要用特殊式写法开启

 .wAutoCell(YES)

这种方法就是传进去的数据源带的model一定要是wBaseModel或者集成它的类
还有自定义cell要带wBaseModel属性

3 如果tableview是需要用section的 比如多少个section和每个section多少rows 需用wSection,默认是row模式
就是section只有一个,row的个数是传进来的数组的个数

.wSection(YES)

而且传进的modelArr的格式需要是多个子数组组成的数组

@[@[],@[],@[]]

3 开启头视图和尾视图高度和视图的定制

//cell高度自定义 默认是用masonry的自动布局
.wCellHeight(^NSInteger(NSIndexPath *indexPath, UITableView *tableView) {
       return indexPath.row == 0 ? 200:UITableViewAutomaticDimension;
})
//cell尾部高度自定义 默认0.01
.wCellFootHeight(^NSInteger(NSInteger section, UITableView *tableView) {
       return 50;
 })
//cell尾部视图自定义 默认无
 .wCellFootView(^UIView *(NSInteger section, UITableView *tableView) {
      UIView *view = [UIView new];
      view.backgroundColor = [UIColor yellowColor];
      return view;
})
//cell头部高度自定义 默认0.01
.wCellHeadHeight(^NSInteger(NSInteger section, UITableView *tableView) {
       return 50;
})
//cell头部视图自定义 默认无
.wCellHeadView(^UIView *(NSInteger section, UITableView *tableView) {
       UIView *view = [UIView new];
       view.backgroundColor = [UIColor redColor];
       return view;
})

4 最重要的一点
wStart属性 需放在最后才有效果,里面执行tableview的delegate和datasource方法

开始解释一下这个类的主要思路

1 我一开始的写法为什么看不到cell的定制的方法

数据源modelArr带的是自定义的wBaseModel,里面携带属性自定义cell类名
wBaseModel可以继承这个类然后自己自定义

wBaseModel *model = [wBaseModel new];
//自定义cell的类名
model.cellName = @"NornalCellOne";
//带过去的参数 这些就不用说了
model.labelName = @"NornalCellOne的文本\nNornalCellOne的文本";
//带过去的参数 这些就不用说了
model.imageName = [NSString stringWithFormat:@"%d.jpg",x3];

然后在tableViewCell的代理方法里

wBaseModel *model = (传进来的数据源对应的indexPath的位置)
if (model) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:model.cellName];
        //kvo赋值  前提是这个自定义cell里要持有个wBaseModel属性且属性名字为model
         [cell setValue:model forKey:@"model"];
         return cell;
}

这种思路是通过model去控制UI的显示,拓展性和重用性比较高,效率快,可以随意修改cell的位置等,而且可以不用写一堆的import 自定义cell类。

2 链式写法 和block

链式编程我就不说了

/*
 * cell的block
 */
typedef UITableViewCell* (^WMZCellCallBlock)(NSIndexPath *indexPath,UITableView* tableView,id model);

/*
 * cell点击的block
 */
typedef void(^WMZSelectCallBlock)(NSIndexPath *indexPath,UITableView* tableView,id model);

/*
 * cell高度的block
 */
typedef NSInteger (^WMZCellHeight)(NSIndexPath *indexPath,UITableView* tableView);

enenen
这个就介绍到这里,觉得对你有用的不妨前往GitHub下载 给个✨ WMZTableView

拓展,思考

这个问题我想了一天都想不出来,处于我比较懒,想在

.wDidSelect(^(NSIndexPath *indexPath, UITableView *tableView,id model) {
      ViewController *VC = [ViewController new];
      VC.type = 1;
      [weakSelf.navigationController pushViewController:VC animated:YES];
 })

调用代码的点击方法的block里 不想用weakSelf想用self,也就是不想在代码块里弱引用,
这个block已经被tableview持有,作为copy属性,self又持有这个tableView,造成对block的间接使用,不用弱引用会造成循环无法释放
我看了一下masonry这个框架,它的block里面可以直接使用self而不会造成循环引用是因为它的block不是作为属性,而是用一个实例方法去接收,相当于block用完就销毁,self没有直接或者间接跟这个block产生关系,而且其操作是同步的,所以不会造成循环引用
而系统的动画里面也不需要用weakself,同理,原因也是self没有对block形成直接或者间接的引用,用完就销毁。

而我这个类操作是异步的
点击的时候,执行tableview的代理didSeleect方法,需要拿到传过去的block
这种时候就必须tableview持有这个block,才能在其他实例方法里拿到
所以在链式调用的时候,传进来的block我赋值给tableview的self.selectBlock属性(copy)

- (WMZTableView *(^)(WMZSelectCallBlock))wDidSelect{
    return ^WMZTableView*(WMZSelectCallBlock wDidSelect){
        if (wDidSelect) {
            self.selectBlock = wDidSelect;
        }
        return self;
    };
}

而要破除循环就要tableview不引用这个block,有点矛盾,怎么都无法做到让self不直接或者间接引用block
试了很多思路都不行,有点无解
有大神有其他方法的或者思路的话可以告知下,不胜感激。

上一篇下一篇

猜你喜欢

热点阅读