1

I am trying to define an array of Rxswift Variable which is of different types (Int, String, Bool, String?, etc...)

So technically I want something like this,

var intVariable = Variable<Int>(10)
var stringVariable = Variable<String>("Hello, RxSwift")
let genericArray = [intVariable, stringVariable]

Reason for this is that, I have a list of variables that i want to subscribe on.

However, i can subscribe on the variables individually like intVariable.asObservable().subscribe, stringVariable.asObservable().subscribe and so on. But if its in an array, I could loop through all the elements and subscribe on it.

The Rxswift Variable is defined as public final class Variable<Element>

P.S I have tried type erasure but no luck. Any help on this would be appreciated!

3
  • I doubt that it is possible? What is the case in which you need to subscribe to variables of different type? Commented May 3, 2017 at 8:40
  • instead of making a loop to subscribe to each individual observable, I suggest to subscribe once to merged sequence of observables. Since you have different type of variables, you could perform a workaround as described here stackoverflow.com/questions/39050059/… Commented May 3, 2017 at 11:49
  • Thanks @Nimble, works great for my case. Commented May 3, 2017 at 17:30

1 Answer 1

1

What you do here depends entirely on what that subscribe closure looks like. If you are doing the same thing to every item in either variable, regardless of type then just map them both to the same type:

let bag = DisposeBag()
let intVariable = Variable<Int>(10)
let stringVariable = Variable<String>("Hello, RxSwift")
let genericArray = Observable.merge([intVariable.asObservable().map { "\($0)" }, stringVariable.asObservable()])
genericArray.subscribe(onNext: { print($0) }).disposed(by: bag)
intVariable.value = 5
stringVariable.value = "Goodby, RxSwift"

prints:

10
Hello, RxSwift
5
Goodby, RxSwift

If you are combining the two items in some way where you need the most recent emitted of each variable and you need to keep the type information then do this:

let genericArray = Observable.combineLatest(intVariable.asObservable(), stringVariable.asObservable())

prints:

(10, "Hello, RxSwift")
(5, "Hello, RxSwift")
(5, "Goodby, RxSwift")

If you only want your subscribe to be triggered when a new element is emitted from both variables, then:

let genericArray = Observable.zip(intVariable.asObservable(), stringVariable.asObservable())

which prints:

(10, "Hello, RxSwift")
(5, "Goodby, RxSwift")

I would avoid the solutions mentioned in (RxSwift merge different kind of Observables)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Daniel T , the problem i saw with combineLatest and zip is that it is limited to 8 arguments and not generic. I feel the first option (with merge) would be the best option for my case, reason being, i just need to listen for updates and run invalidateLayout on any change.
They absolutely are generic. If you have more than 8 arguments, the use combines of combines or zips of zips.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.