[ReactiveCocoa] Optimization fastest で死ぬパターン


開発時は上手く動くのに、リリースモード(Optimization Fastest)で死ぬパターンにハマりました。


class MyViewController : UIViewController {
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        RAC(self.label, "alpha") <~ RACObserve(self.button, "enabled").map { ($0 as Bool) ? 1.0 : 0 }

    ....

開発中は map が実行されて、subscribeNext 前に map の処理が走りますが、Optimization Fastest でコンパイルするとあら不思議、map を素通りして subscribeNext が実行されます。

この場合だと、map が実行されずに、最初の処理で nilsubscribeNext されて、alpha には nil は設定できないよっていう例外が発生します。

対応方法

Build Option で Optimization Level が Release のときに Fastest(-O) になっていると、参照が外れた瞬間に GC されるようで、map 処理がまるごと GC されているようです。

そこで、map が開放されないように weakSelf 節を入れてやります。

RACObserve(self.button, "enabled").map { [weak self] in
    if let weakSelf = self {
        return ($0 as Bool) ? 1.0 : 0
    } else {
        return 0
    }
}

他にやり方ないものでしょうか。。。

参考ソース: source

このソース、Optimization Fastest で動かすと、画面1 (ViewController)を表示しているのに、画面2(SecondViewController)の filter, map, subscribeNext が表示されるという意味の分からない挙動をします。