Is weak self needed for table view cell button closure

后端 未结 3 993
忘掉有多难
忘掉有多难 2021-01-27 04:17

In trying to avoid retain cycles, would using [weak self] in in a UITableViewCell button action be necessary? Example:

in ViewController\'s cellForRow<

3条回答
  •  花落未央
    2021-01-27 05:03

    Yes, it is necessary to use unowned or weak to capture self in this case.

    • Your view controller will most likely have a strong reference to the UITableView
    • The table view has strong reference to it's UITableViewCells and
    • Each cell has strong reference to your buttonAction closure.

    Using self directly will have as an effect a retain cycle.

    This is actually pretty easy to test. Try to present the following view controller and dismiss it:

    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)
        }
    }
    

    You will have the following output:

    TestTableViewController deinit!
    TestTableViewCell deinit!
    

    Now presenting the same view controller without weak and you will see that there is no output, meaning that the deinit functions are not get called and the objects stay in the memory.

提交回复
热议问题