Giter Club home page Giter Club logo

zjtableviewmanager's Introduction

English introduction

关于ZJTableViewManager

强大的数据驱动的TableView,构建复杂TableView从未如此轻松。

使用

直接拖入ZJTableViewManager文件夹里面的文件,或者用cocoapods pod 'ZJTableViewManager', '~> 1.0.8'

适配

Version Swift Xcode
0.2.7 4.0 / 4.2 Xcode10 or later
1.0.3 or later 4.0 ~ 5.2 Xcode10.2 or later

简介

ZJTableViewManager 基于数据驱动页面的理念,接管了UITableViewdelegatedataSource的逻辑,开发者只需要关心数据的处理,避免了冗长的判断,让代码更加易于维护。

比如一个页面里面是UITableView,有5种不同的Cell。按照传统的写法,tableView(_:cellForRowAt:)代理方法里会是这样:

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if condition1 {
            return SimpleStringCell
        }else if condition2 {
            return FullLengthTextFieldCell
        }else if condition3 {
            return TextCell
        }else if condition4 {
            return PasswordCell
        }else if condition5 {
            return SwitchCell
        }else {
            return DefaultCell
        }
}

同时下面两个方法里面也很可能需要写上这一串判断条件。显而易见的缺点:代码冗长

tableView(_:, heightForRowAt:)
tableView(_:, didSelectRowAt:)

其次,实际项目中,很多人直接用IndexPath作为判断条件,大量if else,且当需要对Cell显示顺序做调整时,基于IndexPath的判断就会出问题,改起来特别容易出现Bug。

当然有经验的程序员会抽象出一个type,通过type来判断Cell类型,避免IndexPath的缺陷。这其实已经算是一种数据驱动的**了,相比用IndexPath判断,更加不容易出问题。但是这还不够,这些方法里面依然会有很多if else,影响观感也影响逻辑理解。

所以ZJTableViewManager 在以上的基础上进一步做了封装,效果如下:

就如示例代码所示,不需要处理TableView的delegate和dataSource,不需要那些if else,Item控制Cell处理Cell的事件,我们只要专心用代码描述这个TableView长什么样子,它就会按照我们描述的样子搭建出来。

使用方式

1.系统默认Cell

创建系统默认的cell,使用ZJTableViewItem类,创建之后加入section即可

let item = ZJTableViewItem(title: "测试cell 1")
section.add(item: item)

根据需要可以修改样式为subtitle

item.style = .subtitle
item.detailLabelText = "detail label text"

运行结果:

总结一下系统默认Cell的使用步骤:

  1. 页面上创建一个TableView(StoryBoard拖或者纯代码创建都可以)
  2. 通过这个TableView初始化一个manager
  3. 创建一个Section,加入到manager里
  4. 创建Cell对应的Item,赋值之后加入到section里
  5. manager.reload()

具体不展开说了,系统cell就那几个样式,平时也很少用到,自己尝试吧。

2.自定义Cell

自定义Cell才是我们实际项目中用到最多的,所以这一块需要详细说一下。 我们来尝试自定义这样一个Cell

左边是一个UILabel,右边一个UISwitch,功能是在UISwitch开关时会发出回调,在VC中处理。

首先,新建一个ZJSwitchCell类,继承自UITableViewCell,勾选上Also create XIB file(当然不用XIB,纯代码布局也可以)

在xib文件里面拖上控件,并且把控件和UISwitch的value change事件拖线到Cell文件里面:

下面是重点: 在ZJSwitchCell.swift文件里面写一个ZJSwitchCellItem类,继承自ZJTableViewItem,有三个属性,标题title,开关状态isOn,回调闭包didChanged。

让ZJSwitchCell遵循ZJCellProtocol协议,如图所示,Xcode会弹出提示,点击fix,会自动加上需要的方法和类型

ZJCelltemClass这里填写上前面写好的ZJSwitchCellItem类名

然后Xcode还会有个错误提示,继续点fix,就好了。

可能有时候Xcode自动fix补全的代码有问题,比如说typealias ZJCelltemClass = 出现两遍或者根本没有fix按钮,不要慌,cmd+b编译一下,再试试就好了

然后在cellWillAppear()方法里面写上赋值操作,它等价于tableView(_:, cellForRowAt:)方法。再到valueChanged(:)方法里面,记录UISwitch的状态,并把当前这个item通过回调传出去。Cell部分的自定义就完成了。

最后,在VC里面使用,使用之前需要manager.register(ZJSwitchCell.self, ZJSwitchItem.self)注册一下,这和之前使用系统默认的Cell有区别,自定义的Cell都需要注册一下才可以使用。

class FormViewController: UIViewController {
    var tableView: UITableView!
    var manager: ZJTableViewManager!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView = UITableView(frame: view.bounds, style: .plain)
        view.addSubview(tableView)
        manager = ZJTableViewManager(tableView: tableView)
        manager.register(ZJSwitchCell.self, ZJSwitchItem.self)

        let section = ZJTableViewSection()
        manager.add(section: section)
        
        // Switch Item
        section.add(item: ZJSwitchItem(title: "Switch Item", isOn: false, didChanged: { item in
            zj_log(item.isOn)
        }))

        manager.reload()
    }
}

总结一下自定义Cell的步骤:

  1. 新建Cell(XIB或者纯代码都可以)
  2. 创建Cell对应的Item,通过Item给Cell传值(实际项目中一般是用Item持有Model,在cellWillAppear()中通过item.model取值并赋值到控件里面
  3. 在VC中给把Cell向TableViewManager注册。

其余使用方式参考上面系统默认Cell的使用。

3.Cell固定高度及动态计算高度处理

前面示例的两种Cell高度都是系统默认的44,我们实际项目中需要不同高度的Cell,怎么处理呢?

固定高度: 聪明的同学可能已经发现了,Item控制了Cell的所有表现,所以肯定是通过Item来控制的。Item中有个cellHeight属性,只要给它赋值,就能够控制Cell的高度。 我们可以重写Item对象的init()方法,在里面给一个固定的高度

override init() {
   super.init()
   cellHeight = 100
}

或者在VC里面初始化Item之后,再给cellHeight赋值,都是可以的。

动态高度: 动态高度的前提是使用AutoLayout布局,约束没有缺失,然后在Item赋值好了之后,调用一下autoHeight(:)方法,高度就算好了。

let item = AutomaticHeightCellItem()
item.feed = feed
//计算高度
item.autoHeight(manager)
//把cell加入进section
section.add(item: item)

具体可以看下面的文章,里面说的更详细,这里不展开说了。 Swift UITableViewCell高性能动态计算高度

4.TableView相关事件(如点击事件)

设置点击事件回调:

item.setSelectionHandler { (callBackItem: LevelCellItem) in
    //Do some thing
}

其他事件同理,包括section的一些事件(比如section即将出现之类的回调),具体看Demo。

5.Scroll事件的代理

我们在使用TableView的同时,有时还需要处理Scroll事件,比如说判断滚动已经停止,或者监听滚动事件等,可以通过设置manager.scrollDelegate = self并遵循ZJTableViewScrollDelegate 的方式,获取所有滚动事件的回调,使用方式和UIScrollViewDelegate一样。

Demo:

电商项目的评价、打星评分、添加评论图片,

image image

这里主要有3个cell,一个打星的cell,一个评论的cell,一个添加图片的cell。viewController里只有20行代码,耦合性低。

override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "Demo"
        self.manager = ZJTableViewManager(tableView: self.tableView)
        
        //register cell
        self.manager?.register(OrderEvaluateCell.self, OrderEvaluateItem.self)
        self.manager?.register(ZJPictureTableCell.self, ZJPictureTableItem.self)
        
        //add section
        let section = ZJTableViewSection(headerHeight: 10, color: UIColor.init(white: 0.9, alpha: 1))
        self.manager?.add(section: section)
        
        //add cells
        for i in 0...10 {
          i  //评价cell
            section.add(item: OrderEvaluateItem(title: "评价"))
            let textItem = ZJTextItem(text: nil, placeHolder: "请在此输入您的评价~", ddChanged: nil)
            textItem.isHideSeparator = true
            section.add(item: textItem)
            
            //图片cell
            if i%2 == 1 {
                //只展示图片
                let pictureItem = ZJPictureTableItem(maxNumber: 5, column: 4, space: 15, width: self.view.frame.size.width, superVC: self, pictures: [image])
                pictureItem.type = .read
                section.add(item: pictureItem)
            }else{
                //添加图片
                let pictureItem = ZJPictureTableItem(maxNumber: 5, column: 4, space: 15, width: self.view.frame.size.width, superVC: self)
                pictureItem.type = .edit
                section.add(item: pictureItem)
            }
        }
        
    }

注:

TableView可以storyboard、xib、纯代码初始化,cell可以xib或者纯代码构建

zjtableviewmanager's People

Contributors

jzhang0480 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

zjtableviewmanager's Issues

三级列表选中问题

三级列表中,在第三级需要有单选的功能,但是我在实现的时候,无法刷新页面数据,不知道为啥。麻烦大神帮忙看下。下面是代码
`for item in linelistModel! {
let item0 = ServerListTitleItem()
item0.model = item
item0.isExpand = true
item0.cellHeight = SXRealValue(55)
section.add(item: item0)

        for group in item.groupList! {
            let item1 = ServerVideoItem()
            item1.model = group
            item1.cellHeight = SXRealValue(60)
            item0.addSub(item: item1, section: section)

            for vm in group.vmList! {
                let item2 = ServerContentItem()
                item2.model = vm
                if vmess.flagId == self.selectModel?.flagId {
                    item2.isSelect = true
                    item1.isExpand = true
                }else {
                    item2.isSelect = false
                    item1.isExpand = false
                }
                item2.cellHeight = SXRealValue(55)
                item1.addSub(item: item2, section: section)
                
                item2.setSelectionHandler { (Model: ServerContentItem) in                      
                    self.selectModel = vmessModel.model
                    self.manager.reload()
                }
            }
        }
    }`

autoHeight后约束报错

xib上设置上下左右约束且显示约束没问题,autoHeight后manager.reload报约束错误。不调用autoHeight不报错误,但是撑不开

cellDidAppear() 中执行 item.updateHeight()无效

首先,很好用的组件,感谢🙏
我的场景:自定义ZJTableViewCell子类,有一个textView,要求输入文字的时候动态修改cell的高度
问题:现在初始化item会给textView传递内容(富文本),需要根据内容先计算cell高度,然后发现在cellWillAppear()中无法准确获取cell的宽度,进而导致无法计算文字高度,在cellDidDisappear()可以获取cell宽度,但是对item.cellHeight赋值并执行item.updateHeight()没有生效

你好,请问该框架没有滚动事件穿透吗?

你好,最近遇到一个项目需要用ScrollView嵌套TableView,使用了项目中的ExpandTree功能。
然后发现在滚动scrollView时不能对TableView进行滚动,重写了ScrollView中的Simultaneously返回True也不行,请问是我写的有问题吗?还请指导一下,谢谢。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.