RxSwiftCommunity / Action

Abstracts actions to be performed in RxSwift.
MIT License
875 stars 150 forks source link

Memory leak caused by `bind(to:inputTransform:)` #208

Closed svenfy closed 5 years ago

svenfy commented 5 years ago
import UIKit
import RxSwift
import RxCocoa
import Action

class BButton: UIButton {
    deinit {
        print("按钮销毁:\(self)")
    }
}

class AAA: UIViewController {
    @IBOutlet weak var btn: BButton!

    private var _action: Action<Void, Void>!

    override func viewDidLoad() {
        super.viewDidLoad()

        if navigationController!.viewControllers.count == 2 {
            _action = Action<Void, Void>(workFactory: {
                print("点击了按钮")
                return .empty()
            })
            btn.rx.bind(to: _action, input: ())
        } else {
            btn.addTarget(self, action: #selector(didClick(_:)), for: .touchUpInside)
        }
    }

    @IBAction func didClick(_ sender: Any) {
        if navigationController!.viewControllers.count == 1 {
            navigationController?.pushViewController(AAA(), animated: true)
        }
    }

    deinit {
        print("释放啦:\(self)")
    }
}

执行上述代码,在点击按钮跳转后,再返回,Button得不到释放,打印消息如下:

释放啦:<TestMemory.AAA: 0x7fbd7f408720>

如果将

btn.rx.bind(to: _action, input: ())

改成

btn.rx.action = _action

则Button可以得到释放

释放啦:<TestMemory.AAA: 0x7fbd7f408720>
按钮销毁:<TestMemory.BButton: 0x7fbd7f409840; baseClass = UIButton; frame = (164.5 318.5; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600002510a40>>

总结: 需要将Control+Action.swiftUIBarButtonItem+Action.swiftUIRefreshControl+Action.swift中的

.map { inputTransform(self.base) }

改成

.map { [unowned base] in inputTransform(base) }

测试代码(SourceCode): TestMemory.zip

bobgodwinx commented 5 years ago
  1. It would be kind if you write the description in English
  2. Based on what I read so far, this is not the correct place to file this bug.