Trying to figure out why the deinit is not called in OptionsButton class
func getActionButtonView(delegate: DiscoveryActionViewDelegate) -> UIView {
switch delegate.actionType {
case .showVariants:
let optionButton = OptionsButton(frame: CGRect(x: 0, y: 0, width: 60, height: 20))
optionButton.setup()
optionButton.selectOptionsAction = {
delegate.showVariants(completionBlock: { _ in
optionButton.hideLoader()
})
}
return optionButton
}
The BaseButton is the parent of the HardButton and HardButton is the parent of OptionsButton
class OptionsButton: HardButton {
var selectOptionsAction: () -> Void = {}
func setup() {
setTitleColor(UIColor.color(227, 0, 77), for: .normal)
backgroundColor = .white
titleLabel?.font = UIFont.font(weight: .semiBold, style: .footnote1)
setTitle("list_screen_selectOption_button".localized, for: .normal)
addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
borderColor = UIColor.color(227, 0, 77)
progressColor = UIColor.color(227, 0, 77)
borderWidth = 1
cornerRadius = 4
}
@objc func buttonAction(sender: HardButton) {
self.displayLoader()
self.selectOptionsAction()
}
deinit {
print("deinit OptionsBtn")
}
}
Could anyone help me please the reason or suggest me what's wrong I did? where is/are the leak's
Edit 1-- more code:
enum DiscoveryActionType {
case cartAction
case showVariants
case recommendationCartAction
}
protocol DiscoveryActionViewDelegate: AnyObject {
func showVariants(completionBlock: @escaping (Bool) -> Void)
var actionType: DiscoveryActionType { get }
}
CodePudding user response:
You should confirm with “Debug memory graph”, but selectOptionsAction
is a closure that has a reference to itself (and delegate
, too). This is a classic “strong reference cycle”.
One can use weak
references in the capture lists to break the strong reference cycle(s):
let optionButton = OptionsButton(frame: …)
…
optionButton.selectOptionsAction = { [weak delegate] in
delegate?.showVariants { [weak optionButton] _ in
optionButton?.hideLoader()
}
}
You want to make sure that the button does not keep a strong reference to itself. I have also made sure to use a weak
reference to delegate
, too.
The details may vary, but hopefully this illustrates the idea. Use “debug memory graph” to identify what’s keeping a strong reference to the object in question and use weak
references in your capture lists to break the strong reference cycles.
See this answer for example of how to use “Debug memory graph” feature.