美文网首页
UITableView相关

UITableView相关

作者: Coder_Star | 来源:发表于2019-03-06 19:37 被阅读0次

    1、基础知识

    样式

    UITableView有两种样式(plain,grouped),其中plain为普通列表样式,grouped是分组样式。可以在实例化的时候进行设置,默认是plain。

    //tableview样式
    let  tableView = UITableView()  //plain形式
    let  tableview = UITableView(frame:frame, style:.grouped) //grouped形式
    
    tableview.separatorStyle = .singleLine //设置是否有横线,默认有横线
    
    //tablecell样式
    tablecell.selectionStyle = .gray  //设置cell点击的样式,其中设置为none时候点击时候没有阴影效果
    tablecell.accessoryType = .disclosureIndicator //设置cell尾部样式,箭头还是对号等等
    

    数据源(UITableViewDataSource)

    //行数(必须实现)
    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    //每个cell(必须实现)
    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    //组数,非必须实现 默认是1
    optional public func numberOfSections(in tableView: UITableView) -> Int
    
    

    代理(UITableViewDelegate)

    UITableViewDelegate继承UIScrollViewDelegate,也就是说UITableView其实拥有很多UIScrollView的操作。

    //cell点击监听
    optional public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    //取消点击后产生的阴影
    optional public func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)
    //编辑操作,左滑
    optional public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
    //cell即将展示
    optional public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
    

    2、问题集锦

    1、取消TableView前后默认空白部分

    • 代码示例
        func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
            return 0.01
        }
        func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            return nil
        }
        func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
            return 0.01
        }
        func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
            return nil
        }
    
    • 注意事项
      1.在设置 tableView.delegate = self 时注意将其放在tableView加入其View之前 ( ParentView.addSubview(tableView) ),否则上述代码不会生效。
      2.在ios11系统以下,如果上述header以及footer置为0,则会认为其没有设置高度,还是会默认设置大约为50个像素的高度;ios11系统以上可直接设置为0;

    2、TableView高度自适应

    设置TableView高度自适应一般需要设置estimatedRowHeight以及rowHeight两个属性,并且cell的子控件布局要要实现自动布局(即cell的子控件需要将cell撑满)。其中estimatedRowHeight是一个对cell的预估高度,为其设置一个非负的预估高度可以提高表视图的性能,将一些几何计算的成本从加载时间推迟到滚动时间(预估高度和实际高度差值越小越好);rowHeight设为UITableView.automaticDimension;

    //设置预估高度
    tableView?.estimatedRowHeight = CGFloat((ContentHelp.approveItemContent.count + 1) * ConstantsHelp.itemRowHeight + ConstantsHelp.largePadding)
    //设置高度自适应
    tableView?.rowHeight = UITableView.automaticDimension
    
    //cell自动布局代码
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let tableCell:UITableViewCell = UITableViewCell(style: .default, reuseIdentifier: "cell")
         tableCell.accessoryType = .disclosureIndicator
         let itemUILabel = UILabel()
        //设置换行
         itemUILabel.lineBreakMode = .byWordWrapping
         itemUILabel.numberOfLines  = 0
         tableCell.addSubview(itemUILabel)
         itemUILabel.snp.makeConstraints { (make) in
           make.top.left.right.bottom.equalTo(tableCell) //四个属性重要
         }
      return tableCell
     }
    
    

    3、TableView滚动条常在(具体原理百度上很多,ScrollView同理)

    1、UIImageView扩展(oc代理类文件如何新建自行百度)

    • .h文件(如果项目为swift工程,将该文件在桥接文件中声明以供swift使用)
    #import <UIKit/UIKit.h>
    #define noDisableVerticalScrollTag 836913 //竖向滚动
    #define noDisableHorizontalScrollTag 836914 //横向滚动
    NS_ASSUME_NONNULL_BEGIN
    @interface UIImageView (ForScrollView)
    @end
    NS_ASSUME_NONNULL_END
    
    • .m文件
    #import "UIImageView+Scroll.h"
    @implementation UIImageView (ForScrollView)
    - (void)setAlpha:(CGFloat)alpha{
        
        if (self.superview.tag == noDisableVerticalScrollTag) {
            if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleLeftMargin) {
                if (self.frame.size.width < 10 && self.frame.size.height > self.frame.size.width) {
                    UIScrollView *sc = (UIScrollView*)self.superview;
                    if (sc.frame.size.height < sc.contentSize.height) {
                        return;
                    }
                }
            }
        }
        
        if (self.superview.tag == noDisableHorizontalScrollTag) {
            if (alpha == 0 && self.autoresizingMask == UIViewAutoresizingFlexibleTopMargin) {
                if (self.frame.size.height < 10 && self.frame.size.height < self.frame.size.width) {
                    UIScrollView *sc = (UIScrollView*)self.superview;
                    if (sc.frame.size.width < sc.contentSize.width) {
                        return;
                    }
                }
            }
        }
        
        [super setAlpha:alpha];
    }
    @end
    

    2、为tableView绑定标签

     tableView.tag = Int(noDisableVerticalScrollTag)
    

    以上代码可以实现tableView人工滚动后,滚动条显示后不会再消失。但刚进入不会直接显示滚动条,如果进入页面就直接显示滚动条,则需要添上以下代码;
    3、进入页面直接显示滚动条

    //当tableView绑定完数据后,使用flashScrollIndicators方法
     func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            tableView.flashScrollIndicators() //该方法会自动显示滚动条1~2秒,再配合1,2步骤代码就可以实现滚动条常在了。
        }
    

    4、提供一个获取tableView自适应高度的方法

    近期开发中遇到了一个ScrollView嵌套tableView的场景,因为ScrollView需要依靠其子View的相对约束来计算其ContentSize,所以需要获取到tableView的高度。下面是相关代码。大致思路为在最后一个cell即将展示完毕之后,获取tableView的contentSize,此contentSize便为tableView的高度,将此值更新为tableView的高度约束。(可以提前给tableView设置一个平均高度,然后去更新这个约束,这样即使没有获取到实际高度,也不会有错误)

    //在最后一个cell即将展示完毕之后,获取tableView的contentSize,此contentSize便为tableView的高度,将此值更新为tableView的高度约束
     func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            if list.count > 0 , indexPath.row == list.count-1{
                tableView.snp.updateConstraints{make in
                    make.height.equalTo(tableView.contentSize.height)
                }
            }
        }
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            DispatchQueue.main.asyncAfter(deadline:.now()+0.5){
                QL1(tableView.contentSize.height)
            }
            
        }
    

    5、tableCell点击之后UIAlertController延迟弹出问题处理

    猜测原因:点击事件触发后没有及时刷新UI,或者进入到了其他线程,主线程可能经过几次循环后之后才会发现UI变化,去刷新UI

    //方法1 
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            tableView.deselectRow(at: indexPath, animated: false) //重点是 animated: false ,需要将是否显示动画设为false
    }
    
    //方法2,将弹出框操作放在主线程中进行
    DispatchQueue.main.async {
      //弹出框操作
    }
    
    //方法三
    tableCell.selectionStyle = .none  //不要将点击后颜色变化置为none
    

    6、tablecell复用导致页面数据错位

    可在使用复用的cell前,先删除cell之前的子view

    let id = "cellId"
    var tableCell = tableView.dequeueReusableCell(withIdentifier: id)
    if tableCell == nil{
           tableCell = UITableViewCell(style: .default, reuseIdentifier:id)
    }else{
          if (tableCell?.subviews.count)! > 0{
              tableCell?.subviews.forEach{$0.removeFromSuperview()}
           }
    }
    

    相关文章

      网友评论

          本文标题:UITableView相关

          本文链接:https://www.haomeiwen.com/subject/xlnxpqtx.html