场景:在一个页面中使用懒加载添加两个TableView
我们先用一个TableView作为例子来看
懒加载代码 (在里面设置了一些基础属性和代理)
private lazy var ATabView: UITableView = {
let tableView = UITableView.init()
if tableView.style == .grouped{
tableView.sectionHeaderHeight = 0.0
tableView.sectionFooterHeight = 0.0
tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.001))
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.001))
}
tableView.showsVerticalScrollIndicator = false
tableView.delegate = self
tableView.dataSource = self
tableView.backgroundColor = UIColor.white
tableView.estimatedRowHeight = 0
tableView.estimatedSectionFooterHeight = 0
tableView.estimatedSectionHeaderHeight = 0
tableView.separatorStyle = .none
tableView.tableFooterView = UIView()
return tableView
}()
ViewDidLoad中
ATabView.frame = .init(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
self.view.addSubview(ATabView)
代理方法中的代码
func numberOfSections(in tableView: UITableView) -> Int {
return 10
}
我们这样使用,程序并不会出现什么问题,但是如果我们用同样懒加载的方法,再添加一个BTableView到视图中。并修改代理方法中的代码用于区分两个不同的UITableView
func numberOfSections(in tableView: UITableView) -> Int {
if tableView == ATabView {
return 1
}else {
return 2
}
}
这时候问题就来了,运行后程序卡死,直至报出EXC BAD ACCESS的错误。原因是在懒加载中,我们设置代理的位置不对,当我们在懒加载中设置完ATabView的代理后,又修改了一些属性,导致在ATabView还没创建完成时,执行了代理方法。而在代理方法中,又使用了ATabView,这样在代理方法中使用到的ATabView为空,又会执行懒加载。形成了无限递归的问题。
解决办法
在懒加载中创建ATabView时,需要将所有的属性设置完成后,最后再设置代理。这样代理方法不会提前执行,确保了在代理方法中用到ATabView时,他是被创建好的。这样就不会无限递归了。
另一种情况
多数情况下,我们可能会给UITableView加一个扩展,方便我们每次创建UITableview对象
public extension UITableView {
static func initCommonTableView(style: UITableView.Style = UITableView.Style.plain, dataSourceDelegate: NSObject, tableViewDelegate: NSObject) -> UITableView {
let tableView = UITableView.init(frame: .zero, style: style)
if tableView.style == .grouped{
tableView.sectionHeaderHeight = 0.0
tableView.sectionFooterHeight = 0.0
tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.001))
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0.001))
}else {
tableView.tableFooterView = UIView()
}
tableView.showsVerticalScrollIndicator = false
tableView.backgroundColor = UIColor.white
tableView.estimatedRowHeight = 0
tableView.estimatedSectionFooterHeight = 0
tableView.estimatedSectionHeaderHeight = 0
tableView.separatorStyle = .none
tableView.delegate = tableViewDelegate as? UITableViewDelegate
tableView.dataSource = dataSourceDelegate as? UITableViewDataSource
return tableView
}
}
在懒加载调用的时候
private lazy var ATabView: UITableView = {
let tableView = UITableView.initCommonTableView(dataSourceDelegate: self, tableViewDelegate: self)
return tableView
}()
问题: 如果这时候我们在懒加载中修改tableview的属性,并在代理方法中使用ATabView,还会出现之前无限递归调用懒加载的问题吗?
private lazy var ATabView: UITableView = {
let tableView = UITableView.initCommonTableView(dataSourceDelegate: self, tableViewDelegate: self)
tableView.tableFooterView = UIView.init(frame: .init(x: 0, y: 0, width: SCREEN_WIDTH, height: 80))
return tableView
}()
经过尝试后发现,并没有不会出现这种问题。为什么呢?我们在扩展中最后的代码设置了代理,然后在懒加载中又修改了tableview的tableFooterView属性,为什么不会无限递归呢?
我们尝试在扩展方法中,注释掉给tableview的tableFooterView赋值的操作,再执行,发现再次出现了无限递归的情况。
结论
tableview设置代理后,再次修改属性时,需要看这个属性,在设置代理前是否被赋值过。如果有,则不会触发代理事件。如果没有,则会触发代理事件。
总之我们在懒加载中给tableview设置代理后,尽可能不要再对tableview进行属性设置。如果需要设置属性,把设置操作放在懒加载之外,也就是ATabview对象被创建后再执行ATabview的属性设置