UITableView相关

2019-03-06  本文已影响0人  Coder_Star

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
    }

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代理类文件如何新建自行百度)

#import <UIKit/UIKit.h>
#define noDisableVerticalScrollTag 836913 //竖向滚动
#define noDisableHorizontalScrollTag 836914 //横向滚动
NS_ASSUME_NONNULL_BEGIN
@interface UIImageView (ForScrollView)
@end
NS_ASSUME_NONNULL_END
#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()}
       }
}
上一篇下一篇

猜你喜欢

热点阅读