Swift中UITableView的动态DataSource交换

时间:2016-08-21 16:47:07

标签: ios swift uitableview

我是iOS / Swift开发的新手,并且在为UITableView进行DataSource的动态交换时遇到问题 - 请注意,我没有交换Delegate,只是数据源。

我已经在Stack Overflow上阅读了其他类似的问题/回复,但找不到与我的情况相关的问题/答案。通常它们是关于在“viewDidLoad”(例如this onethis one)上设置DataSource,而我的情况是关于当用户按下按钮时交换DataSource。我的代码中不存在引用问题中的问题。

这是我的代码大纲。我将buttonPress方法连接到故事板中的TouchUpInside事件:

class ViewController: UIViewController, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!

    ...    

    @IBAction func buttonPress(sender: UIButton) {

        ...

        self.tableView.dataSource = DummyDataSource()
        self.tableView.delegate = self
        self.tableView.reloadData()

    }

    ...

}

...这是我的数据源类:

import UIKit

class DummyDataSource: NSObject, UITableViewDataSource {

    let names = ["A", "B", "C"]

    func tableView(tableView: UITableView,
                     numberOfRowsInSection section: Int) -> Int {
        return names.count
    }

    func tableView(tableView: UITableView,
                     cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        var cell = tableView.dequeueReusableCellWithIdentifier(simpleTableIdentifier) as UITableViewCell?

        if ( cell == nil ) {
            cell = UITableViewCell( style: UITableViewCellStyle.Default,
                                reuseIdentifier: simpleTableIdentifier)
        }

        cell!.textLabel?.text = names[indexPath.row]
        return cell!

    }

}

当我按下按钮时,我可以看到正确调用了pressButton方法,但数据没有显示在tableView中(没有错误 - 只是没有数据)。有什么想法吗?谢谢。

1 个答案:

答案 0 :(得分:5)

UITableView dataSource属性为unsafe_unretainedweakdepending on which version of iOS。无论哪种方式,与任何其他代表一样,它也没有强有力的参考。

所以当你写这样的一行时:

self.tableView.dataSource = DummyDataSource()

您新实例化的DummyDataSource()媒体资源没有指向它的任何强引用。因此,它立即由ARC发布。

如果我们希望它能够坚持下去,我们需要对数据源保持强有力的参考。

我的建议是将数据源属性添加到视图控制器,这可以保留强引用。我们还将使用此属性的didSet来设置表格视图的数据源属性并重新加载其数据。

var dataSource: UITableViewDataSource? {
    didSet {
        tableView?.dataSource = dataSource
        tableView?.reloadData()
    }
}

我们使用optional-chaining来防止在加载视图之前设置的数据源并填充tableView属性。否则,我们将尝试解开nil时出现致命错误。

我们不需要在其他任何地方的表视图上设置数据源属性。我们需要在其他任何地方调用reloadData()的唯一原因是我们的数据源本身是否可以更改它所代表的数据。但是,重要的是reloadData()与重置dataSource同步调用,以防止某些可能的索引跳出崩溃。