Add a rx.value to my CustomView
Asked Answered
S

2

6

Lets say i have a CustomView with a value in it. I want to expose that value to the world using rx.value (Observable) instead of having to access it by value (Int).

final class CustomView: UIView {
   var value: Int = 0
   ...
}

I copied this from UIStepper+Rx:

extension Reactive where Base: CustomView {

    var value: ControlProperty<Int> {
        return base.rx.controlProperty(editingEvents: [.allEditingEvents, .valueChanged],
            getter: { customView in
                customView.currentValue
        }, setter: { customView, value in
            customView.currentValue = value
        }
        )
    }

}

final class CustomView: UIControl {

    fileprivate var currentValue = 1 {
        didSet {
            checkButtonState()
            valueLabel.text = currentValue.description
        }
    }

   // inside i set currentValue = 3
}

But customView.rx.value doesnt emit any values

Selina answered 21/6, 2018 at 13:44 Comment(1)
Can u pls help me on this? " Value of type 'Reactive<Base>' has no member 'controlProperty' "Pledge
I
11

The missing thing is, you need to send action on UIControl. Check the next example:

class CustomView: UIControl {
    var value: Int = 0 {
        didSet { sendActions(for: .valueChanged) } // You are missing this part
    }
}

extension Reactive where Base: CustomView {

    var value: ControlProperty<Int> {
        return base.rx.controlProperty(editingEvents: UIControlEvents.valueChanged,
                                       getter: { customView in
                                        return customView.value },
                                       setter: { (customView, newValue) in
                                        customView.value = newValue})
    }

}
Ineffaceable answered 22/6, 2018 at 12:48 Comment(2)
Can u pls help me on this? "Value of type 'Reactive<Base>' has no member 'controlProperty'"Pledge
You have to import RxCocoaHaemophiliac
C
0

I think you want to use a Subject, either a PublishSubject or Variable.

A PublishSubject starts as an empty sequence and emits only new Next events to its subscribers. A Variable allows to set an initial value at the start and replays the latest or initial value to subscribers. Variables are guaranteed not to fail, it will not and cannot emit an error. This tutorial helps https://medium.com/@dkhuong291/rxswift-subjects-part1-publishsubjects-103ff6b06932

so you would need to set value as to your subjects like so:

 var myValue = PublishSubject<Int>()
 ...
 myValue.onNext(2)

or

 var myValue = Variable<Int>(0)
 ...
 myValue.value = 2

then subscribe to it:

var disposeBag = DisposeBag()
myValue.asObservable()
    .subscribe({
        print($0)
    }).disposed(by: disposebag) 

Also, you might just want to bind the value to your UILabel using a string Subject.

var myValue = PublishSubject<String>()
...
myValue.onNext("\(4)")
...
func viewDidLoad() {
     super.viewDidLoad()
     myValue.asObservable().bind(to: valueLabel.text)
}

Alternatively, given that you want to set your value via rx.value. You would need to create a DelegateProxy class of you customView with RxCocoa. This is the same as creating a delegate for your CustomView where you can delegate your properties by setting their value anywhere you want and listen to them via customView.rx...

I posted something on this last month What delegate cant do than Reactive?. its really helping me control my custom views properties with ease.

Creedon answered 22/6, 2018 at 8:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.