如何实例化弱委托而不触发“由于属性'tableViewDelegate'为'弱',实例将被立即释放”

时间:2019-03-02 09:04:50

标签: swift delegates weak

我试图将tableView的数据源分离为单独的委托对象。由于该委托需要在某个时刻访问表视图,因此我需要引用该委托中的委托对象。并且由于两者都是类,因此我需要通过使委托JSON.parse()

来避免强引用周期

为此,我尝试了以下代码。

weak

当我尝试实例化委托Xcode时,抛出警告:“由于属性'tableViewDelegate'为'弱',实例将被立即释放”

要解决此问题,请执行以下操作:

class MyViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    weak var tableViewDelegate: UITableViewDataSource?

    override func viewDidLoad() {
        super.viewDidLoad()
        tableViewDelegate = TableViewDelegate() // throwing a warning
        tableView.dataSource = tableViewDelegate
    }
}

请确认以下条件是否成立:通过在viewDidLoad()方法中初始化委托,我没有创建强引用的危险,因为保存该实例的变量会在我们离开范围时立即被释放。该方法。或换一种说法:我们唯一需要担心的是变量(指向类)创建强引用的唯一原因是,该变量是否在类级别上初始化,因此将在该类存在的情况下持续存在。

对吗?

2 个答案:

答案 0 :(得分:2)

  

请确认以下条件是否成立:通过在viewDidLoad()方法中初始化委托,我没有创建强引用的危险,因为保存该实例的变量会在我们离开范围时立即被释放。该方法。

正确。一旦声明let的范围退出,强引用就会消失。

不幸的是,这意味着您的代表仍将被释放。您所要做的就是使警告静音。

基本上,您需要对委托 somewhere 进行强有力的引用,否则它将立即消失。我的感觉是,您应该使MyViewController中的引用更强。只要您的委托不包含对视图控制器的强引用,就不会有强引用周期。如果您需要在委托中引用MyViewController,请使它成为一个弱者,即视图控制器拥有委托,而不是委托拥有视图控制器。


回复以下评论:

  

我发现的几乎所有教程的委托属性都很弱,因此这似乎是标准做法。

是的,这是相当的标准惯例,可可中也有例外。但是,通常的做法是在委托对象中对委托的引用很少。在您的情况下,委派对象是UITableView,而不是MyViewController。在您的第一个Internet示例中,FileImporter与代码中的UITableView类似。在第二个示例中,DetailViewController是委派对象。

如果考虑一下,将使用TableViewDelegate来代替MyViewController遵守协议。 MyViewController拥有委托是绝对合理的。

答案 1 :(得分:0)

这是我解决此问题的方法:

    let dataSource = MyDataSource()

    lazy var viewModel : MyViewModel = {
        let viewModel = MyViewModel(dataSource: dataSource)
        return viewModel
    }()

,然后在viewDidLoad()中:

    tableView.delegate = self
    tableView.dataSource = dataSource

您可以看到完整的演示项目here