Swift访问lazy var无限循环导致崩溃

jky*_*yin 2 uitableview swift

我认为惰性 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!
    }
}
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我吗?

Dan*_*all 6

问题是创建表视图的闭包最终是递归的。

  • 当您在桌子上设置 tableFooterView 时,它会立即尝试找出该页脚是否应该立即绘制/可见/在屏幕上。

  • 要知道页脚是否可见,表视图必须找出当前应显示多少行,因此它会向数据源(您的视图控制器)询问第一部分中的行数

  • 在你的方法中tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int,你有这条线if tableView == hotStockTableView {。这尝试访问惰性hotStockTableView变量,它仍然没有完成初始化,因为该闭包是首先调用此代码的

  • 因此,惰性 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
}()
Run Code Online (Sandbox Code Playgroud)

现在你的代码就可以正常工作了。