You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中TableViewDataSource分离到其他类的两种写法为何一失效一正常?

嘿,这个问题其实是iOS开发里很常见的ARC内存管理坑,两种写法看似等价,但本质差在对象的生命周期上,咱们一步步说清楚:

第一种写法失效的原因

你看这段代码:

override func viewDidLoad() {
    super.viewDidLoad();
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    tableView.dataSource = TableViewDataSource();
}

这里的TableViewDataSource()是在viewDidLoad方法内部创建的局部对象——当viewDidLoad执行完毕后,这个对象没有任何强引用指向它。iOS的ARC(自动引用计数)会立刻销毁这个没有被强引用持有的对象。

而UITableView的dataSource属性是**弱引用(weak)**类型(UIKit里几乎所有delegate/dataSource都是弱引用,目的是避免循环引用),所以当数据源对象被销毁后,tableView的dataSource就变成了nil,自然无法响应numberOfRowsInSection、cellForRowAt这些数据源方法,表视图也就没法正常显示内容了。

第二种写法能正常工作的原因

再看这段代码:

var dataSource:TableViewDataSource!;
override func viewDidLoad() {
    super.viewDidLoad();
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    dataSource = TableViewDataSource();
    tableView.dataSource = dataSource;
}

这里你把dataSource声明为ViewController的存储属性,ViewController本身会对这个数据源对象持有一个强引用。只要ViewController没有被销毁,这个数据源对象就会一直保存在内存中,tableView的弱引用dataSource就能一直指向有效的对象,所以表视图可以正常调用数据源方法,显示内容。

总结一下

核心原则就是:你需要给自定义的数据源对象一个强引用持有者,避免它被ARC提前销毁。把数据源存为控制器的属性是最常规、最稳妥的做法,当然你也可以用其他方式(比如闭包捕获、全局存储等)来保持强引用,但属性方式是最符合iOS开发规范的。

内容的提问来源于stack exchange,提问作者Murad Sofiyev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:34:34