関数でも解放されない。
タイトル適当ですが、手元で動かしたものをサクッと出力。
androidのxmlとかvueやanglureのように、swiftでも宣言的にUIを定義してみようと、少しいじってみた。
こんな感じのボタンクラスがあるとして
import UIKit final class Button: UIButton { convenience init(title: String, onClick: () -> Swift.Void) { self.init(frame: .zero) addTarget(self, action: #selector(actionClick), for: .touchUpInside) clickHandler = onClick setTitle(title, for: .normal) } private var clickHandler: (() -> Swift.Void)? @objc private func actionClick() { clickHandler?() } deinit { print("deinit") } }
こんな感じで関数を渡してあげたらスッキリしていい感じと思ったけど、
final class ViewController: UIViewController { private lazy var button = Button(title: "解放されない", onClick: onClickButton) private func onClickButton() { dismiss(animated: true, completion: nil) } }
クロージャーがselfをキャプチャするのを考えると、上で関数渡すだけだとbuttonがdeinitしなかった。
final class ViewController: UIViewController { private lazy var button = Button(title: "解放されない") { dismiss(animated: true, completion: nil) } private lazy var button1 = Button(title: "解放される") { [weak self] in self?dismiss(animated: true, completion: nil) } }
結局クロージャーを渡している。
final class ViewController: UIViewController { private lazy var button = Button(title: "解放される", onClick: onClickButton) private lazy var onClickButton = { [weak self] in self?.dismiss(animated: true, completion: nil) } }