自定义按钮内存问题中的内存泄漏
memory leaking in custom button memory problems
试图找出为什么没有在 OptionsButton 中调用 deinit 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
}
BaseButton 是 HardButton 的父级,而 HardButton 是 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")
}
}
谁能帮我找出原因或告诉我我做错了什么? is/are 泄漏的地方
编辑 1--
更多代码:
enum DiscoveryActionType {
case cartAction
case showVariants
case recommendationCartAction
}
protocol DiscoveryActionViewDelegate: AnyObject {
func showVariants(completionBlock: @escaping (Bool) -> Void)
var actionType: DiscoveryActionType { get }
}
您应该通过“调试内存图”进行确认,但是 selectOptionsAction
是一个引用自身的闭包(delegate
也是)。这就是经典的“强引用循环”。
可以在捕获列表中使用 weak
引用来打破强引用循环:
let optionButton = OptionsButton(frame: …)
…
optionButton.selectOptionsAction = { [weak delegate] in
delegate?.showVariants { [weak optionButton] _ in
optionButton?.hideLoader()
}
}
您要确保按钮不会对自身保持强引用。我也确保使用 weak
对 delegate
的引用。
细节可能有所不同,但希望这能说明这个想法。使用“调试内存图”来确定是什么保持对相关对象的强引用,并在捕获列表中使用 weak
引用来打破强引用循环。
有关如何使用“调试内存图”功能的示例,请参见。
试图找出为什么没有在 OptionsButton 中调用 deinit 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
}
BaseButton 是 HardButton 的父级,而 HardButton 是 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")
}
}
谁能帮我找出原因或告诉我我做错了什么? is/are 泄漏的地方
编辑 1-- 更多代码:
enum DiscoveryActionType {
case cartAction
case showVariants
case recommendationCartAction
}
protocol DiscoveryActionViewDelegate: AnyObject {
func showVariants(completionBlock: @escaping (Bool) -> Void)
var actionType: DiscoveryActionType { get }
}
您应该通过“调试内存图”进行确认,但是 selectOptionsAction
是一个引用自身的闭包(delegate
也是)。这就是经典的“强引用循环”。
可以在捕获列表中使用 weak
引用来打破强引用循环:
let optionButton = OptionsButton(frame: …)
…
optionButton.selectOptionsAction = { [weak delegate] in
delegate?.showVariants { [weak optionButton] _ in
optionButton?.hideLoader()
}
}
您要确保按钮不会对自身保持强引用。我也确保使用 weak
对 delegate
的引用。
细节可能有所不同,但希望这能说明这个想法。使用“调试内存图”来确定是什么保持对相关对象的强引用,并在捕获列表中使用 weak
引用来打破强引用循环。
有关如何使用“调试内存图”功能的示例,请参见