ReactiveCocoa / ReactiveSwift

Streams of values over time

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is it possible to update the `value` of a `MutableProperty` in a block triggered by observing that `MutableProperty`?

nservidio opened this issue · comments

ReactiveSwift 6.0.0
Xcode 10.3

Hi there! This may be a dumb question. I'm wondering, is it possible to update the value of a MutableProperty in a block triggered by observing that MutableProperty? When I run the following code, and click the button a few times, I get a Lock.UnfairLock.lock() error.

import UIKit
import ReactiveSwift

class Foo {
    let mutableProperty = MutableProperty<[Int]>([1, 2, 3, 4, 5])

    init() {
        mutableProperty.signal.skipRepeats().observeValues { (list) in
            print(list)
            if list.count <= 2 {
                self.mutableProperty.value.append(contentsOf: [6, 7, 8])
            }
        }
    }
}

class ViewController: UIViewController {
    let foo = Foo()
    
    @IBAction func didTapButton(_ sender: Any) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.foo.mutableProperty.value.removeFirst()
        }
    }
}

However, I have a similar version of this working in another project. I'll try to sanitize it so I can post. I'm just wondering if what I'm trying to do is not possible, or if there is another ReactiveSwift construct that would help.

As far as I know recursive signals are not allowed in ReactiveSwift. While there may be ways to move around it, it might be easier to refactor the code to avoid the need for a recursive signal.

In your current example it might be better to create a value type that makes sure that the list never gets to the point where it has fewer than 3 elements:

struct State {
    var list = [1, 2, 3, 4, 5] {
        didSet {
            if list.count <= 2 {
                list.append(contentsOf: [6, 7, 8])
            }
        }
    }
}

class Foo {
    let mutableProperty = MutableProperty(State())

    init() {
    }
}

class ViewController: NSObject {
    let foo = Foo()

    @IBAction func didTapButton(_ sender: Any) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.foo.mutableProperty.modify { $0.list.removeLast() }
        }
    }
}

Hello. 👋 Thanks for opening this issue. Due to inactivity, we will soft close the issue. If you feel that it should remain open, please let us know. 😄