我认为懒惰的var {}()应该运行一次。但今天我遇到这个问题困扰着我。我有任何想法。我哭了。
这是复制课:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private lazy var hotStockTableView: UITableView = {
let tableView = UITableView()
print("hotStockTableView ======> \(tableView) \n")
tableView.delegate = self
tableView.dataSource = self
// Here cause crash.
tableView.tableFooterView = UIView() // if comment this line, everthing is ok.
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(hotStockTableView)
hotStockTableView.frame = view.bounds
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("tableView =====> \(tableView) \n")
if tableView == hotStockTableView {
return 5
} else {
return 0
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
}
cell?.textLabel?.text = "\(indexPath.row)"
return cell!
}
}
有人可以帮助我吗?
答案 0 :(得分:2)
问题是你创建表视图的闭包最终是递归的。
当您在桌面上设置tableFooterView时,它会立即尝试找出是否应立即绘制/显示该页脚/屏幕。
要知道页脚是否可见,表视图必须找出当前应显示的行数,因此它会向数据源(视图控制器)询问第一行中的行数部分
在方法tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
中,您有if tableView == hotStockTableView {
行。这会尝试访问仍未完成初始化的惰性hotStockTableView
var,因为该闭包是首先调用此代码的
因此,懒惰的var闭包再次启动并递归地反复执行相同的步骤,直到堆栈溢出并崩溃。
幸运的是,解决方案很简单。如果尚未设置数据源,则添加表视图页脚将永远不会调用您的行数数据源方法。因此,只需将延迟闭包中的代码顺序更改为以下内容:
private lazy var hotStockTableView: UITableView = {
let tableView = UITableView()
print("hotStockTableView ======> \(tableView) \n")
tableView.tableFooterView = UIView()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
return tableView
}()
现在你的代码工作得很好。
答案 1 :(得分:1)
关于lazy
个变量有a good answer on SO:
就线程安全而言,
lazy var
不是线程安全的 在斯威夫特。这意味着如果两个不同的线程尝试访问相同的
lazy var
同时,在这个变量初始化之前,它是 可能其中一个线程将访问部分构造 实例
我建议在创建delegate
视图后尝试设置dataSource
和lazy
。在完全初始化之前,delegate
或dataSource
可能会访问它。