Ios 表视图单元格按钮关闭是否需要弱自我

Ios 表视图单元格按钮关闭是否需要弱自我,ios,swift,uitableview,uibutton,retain-cycle,Ios,Swift,Uitableview,Uibutton,Retain Cycle,在试图避免保留周期时,是否有必要在UITableViewCell按钮操作中使用中的[弱自我]?例如: 在ViewController的cellForRow cell.buttonAction = { (cell) [weak self] in self.someFunction() } 在TableViewCell类中 var buttonAction: ((UITableViewCell) -> Void)? @IBAction func buttonPressed(_ s

在试图避免保留周期时,是否有必要在UITableViewCell按钮操作中使用中的
[弱自我]?例如:

在ViewController的
cellForRow

cell.buttonAction = { (cell) [weak self] in
     self.someFunction()
}
在TableViewCell类中

var buttonAction: ((UITableViewCell) -> Void)?

@IBAction func buttonPressed(_ sender: Any) {
     buttonAction?(self)
}

是的,在这种情况下,有必要使用
无主
来捕获
自身

  • 您的视图控制器很可能对
    UITableView
  • 表视图对其
    UITableViewCells
  • 每个单元格都强烈引用您的
    按钮操作
    闭包
直接使用self会产生一个保留周期

这实际上很容易测试。尝试呈现以下视图控制器并将其关闭:

class TestTableViewCell: UITableViewCell {
    var closure: (() -> Void)?
    
    deinit {
        print("TestTableViewCell deinit!")
    }
}

class TestTableViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.register(TestTableViewCell.self, forCellReuseIdentifier: "TestTableViewCellIdentifier")
    }
    
    deinit {
        print("TestTableViewController deinit!")
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCellIdentifier", for: indexPath) as! TestTableViewCell
        
        cell.closure = { [weak self] in
            guard let self = self else { return }
            self.testFunction()
        }
        
        return cell
    }
    
    func testFunction() {}
}

// Test present
let controller = TestTableViewController()
present(controller, animated: true) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        self.dismiss(animated: true)
    }
}
您将获得以下输出:


现在,在没有弱的情况下显示相同的视图控制器,您将看到没有输出,这意味着不会调用
deinit
函数,并且对象保留在内存中。

是的,在这种情况下,有必要使用
无主
来捕获
自身

  • 您的视图控制器很可能对
    UITableView
  • 表视图对其
    UITableViewCells
  • 每个单元格都强烈引用您的
    按钮操作
    闭包
直接使用self会产生一个保留周期

这实际上很容易测试。尝试呈现以下视图控制器并将其关闭:

class TestTableViewCell: UITableViewCell {
    var closure: (() -> Void)?
    
    deinit {
        print("TestTableViewCell deinit!")
    }
}

class TestTableViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.register(TestTableViewCell.self, forCellReuseIdentifier: "TestTableViewCellIdentifier")
    }
    
    deinit {
        print("TestTableViewController deinit!")
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCellIdentifier", for: indexPath) as! TestTableViewCell
        
        cell.closure = { [weak self] in
            guard let self = self else { return }
            self.testFunction()
        }
        
        return cell
    }
    
    func testFunction() {}
}

// Test present
let controller = TestTableViewController()
present(controller, animated: true) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        self.dismiss(animated: true)
    }
}
您将获得以下输出:


现在,在没有弱的情况下显示相同的视图控制器,您将看到没有输出,这意味着不会调用
deinit
函数,并且对象保留在内存中。

如果您不使用tableviewcell的对象,并且只希望在单元格上执行操作,请执行此操作

var buttonAction: (() -> Void)?

@IBAction func buttonPressed(_ sender: Any) {
     buttonAction?()
}
在牢房里用这个

cell.buttonAction = { [weak self] in
     self?.someFunction()
}
对于check-retain循环,我通常使用这个选项来检查内存是否被保留。

如果您不使用tableviewcell的对象,并且只希望对单元格执行操作,请执行此操作

var buttonAction: (() -> Void)?

@IBAction func buttonPressed(_ sender: Any) {
     buttonAction?()
}
在牢房里用这个

cell.buttonAction = { [weak self] in
     self?.someFunction()
}
对于check-retain循环,我通常使用这个选项来检查内存是否被保留。

需要考虑的关键问题是:

var buttonAction: ((UITableViewCell) -> Void)?
您提供在实例属性中长期存储函数

现在想想谁指谁/拥有谁。视图控制器拥有自己的视图,该视图是或拥有拥有单元格的表视图。同时,细胞也拥有这一功能。如果函数强烈引用我刚才提到的任何对象,那就是一个保留循环。这是一个经典的保留周期,是如何进行保留周期的绝对模型



[我想补充一句关于如何测试这些东西的话。有一种非常便宜且简单的方法:将视图控制器包装在导航控制器中,再加上一个空白的根视图控制器,这样你就可以将视图控制器推到它上。在视图控制器中实现
deinit
。现在运行应用程序,推送视图控制器,玩with它一点,然后用后退按钮弹出它。如果没有调用
deinit
,则您有一个保留周期。]

需要考虑的关键行是:

var buttonAction: ((UITableViewCell) -> Void)?
您提供在实例属性中长期存储函数

现在想想谁引用了谁/拥有了谁。视图控制器拥有自己的视图,或者拥有拥有单元格的表视图。同时,单元格拥有函数。如果函数强烈引用了我刚才提到的任何对象,那就是一个保留循环。这是一个经典的保留循环,是保留循环的绝对模式。



[我想补充一句关于如何测试这些东西的话。有一种非常便宜且简单的方法:将视图控制器包装在导航控制器中,再加上一个空白的根视图控制器,这样你就可以将视图控制器推到它上。在视图控制器中实现
deinit
。现在运行应用程序,推送视图控制器,玩with它一点,然后用后退按钮弹出它。如果未调用
deinit
,则您有一个保留周期。]

为什么不在内存图调试器中查看它,这样你就可以自己查看?这是一个很好的学习机会为什么不在内存图调试器中查看它,这样你就可以自己查看?这是一个很好的学习机会。你能用一点代码写下当点击后退按钮时如何测试vc从导航vc中脱离的位置吗你更喜欢这种测试的扩展,或者像你说的那样写几行代码。我应该为我的问题问一个新问题,还是在这里就可以了?你能用一点代码写下当点击后退按钮时你是如何测试vc从导航vc中分离的吗?你更喜欢这种测试的扩展,还是像你说的那样写几行代码。我应该为我的问题问一个新问题,还是在这里可以?