13

To create an observable array using RxSwift in Swift 2, I use to do this:

[1, 2, 3].toObservable().subscribeNext { print($0) }

But in Swift 3, it doesn't work anymore, I got this error:

Value of type '[Int]' has no member 'toObservable'

How can I create an RxSwift observable array from a swift array?

kamwysoc
  • 6,709
  • 2
  • 34
  • 48
pableiros
  • 14,932
  • 12
  • 99
  • 105

2 Answers2

21

The toObservable array-to-Observable constructor was deprecated.

Creating a cold observable

Use the from operator instead to create a cold observable:

let stream : Observable<Int> = Observable.from([1,2,3])

Or if you need the whole array as an entry, use the just operator to create a cold observable.

let singleEmissionStream : Observable<[Int]> = Observable.just([1,2,3])

Elements of the array at the time that the from or just operator is called will be final set of emissions on the onNext events and will end with an onCompleted event. Changes to the array will not be recognized as new events for this observable sequence.

This means that if you don't need to listen to changes on that array, you can use the just and the from operator to create the observable.

But what if I need to listen to changes on the array elements?

To observe changes on an array [E], you need to use a hot observable like the Variable RxSwift unit, as specified in the answer by k8mil. You will have an instance of type Variable<[E]> wherein each onNext emission is the current state of the array.

What is the difference between a cold and a hot observable?

A distinction between cold and hot observables are explained in the documentation of RxSwift and in reactivex.io. Below is a short description of cold observables in comparison to hot observables.

Cold observables start running upon subscription, i.e., the observable sequence only starts pushing values to the observers when Subscribe is called. [...] This is different from hot observables such as mouse move events or stock tickers which are already producing values even before a subscription is active.

The from and the just operators take the current state of the array when the code runs, thus finalizing the set of emissions it will fire for its observable sequence, no matter when it is subscribed to. That is why changes to the set of elements in the array at a later time will not change the set of elements recognized as the emissions during the creation of the observable using the from or just operators.

dsapalo
  • 1,819
  • 2
  • 19
  • 37
  • Are you sure about that stream you create will work correctly? I've tested it and changes on the array not trigger any event. Could you provide some code with subscription? Thanks You can look at my code: https://pastebin.com/phbNjmec – kamwysoc Jun 30 '17 at 06:11
  • 1
    Hi, I must have misread the question. I thought that the question was how to arrive at an `Observable` from a Swift array of type `[E]`. It did not specify whether it was a hot observable or a cold observable. I'll note that the approach I proposed is a cold observable, and explain its difference with your hot observable implementation which uses a `Variable`. – dsapalo Jul 01 '17 at 06:36
18

In Swift 3 using RxSwift 3.0 I will do that like this:

var array: Variable<[Int]> = Variable([1, 2, 3])
array.asObservable().subscribe(onNext: {
        updatedArray in
        print(updatedArray)
})
array.value.append(4) // it will trigger `onNext` event 

So the main difference is that you have to create an Variable object instead of using an explicit array.

kamwysoc
  • 6,709
  • 2
  • 34
  • 48