I'm studying RXSwift, and I'm a little confuse about Observables. I've understood the theory, that it can emit events "over time". But, I must initialize it with a value, subscribe, and user that value (which is pointless), but I cannot change the value of that observable later, so, whats the point of saying that it can emit values "over time"??? Can someone clarify it to me? Thanks a lot!
2 Answers
It's true that you can't change the value of an Observable
directly because that's not the point of having an Observable
. In that case you can just return a value and mutate it inline without using observable.
Think of observable simply as a sequence of events ordered by time. On a sequence data structure you're not directly manipulating / mutating what's inside them, what you do normally is to map them into something else, filter the events that you want to exclude based on a certain condition, or combine them with another sequence.
For example, you can map
these events which can be described as e(t)
, with the horizontal line represents the flow of time.
--1--2--3--4--5--6--|
into its multiples:
func duplicate(event: Int) -> Int {
return event * 2
}
--2--4--6--8--10--12--|
afterwards, filter
them
func clip(event: Int) -> Int {
return event < 10
}
--2--4--6--8--|
Then, think of these sequences as any kind of sequence, it can be a result of multiple HTTP responses from multiple requests that you chain together.
It can be a Void
that usually results from a UIControl
event. You can take a look at the documentation here:
ControlProperty / ControlEvent
However if you really need mutation, take a look at BehaviorRelay
.
The mistake you are making is in assuming that you must "initialize [an observable] with a value"; you don't do that. Instead you initialize an observable with a procedure that produces (zero or more) values.
Maybe concrete example will help...
let search = searchTextField.rx.text.orEmpty.asObservable()
The search
variable above is of type Observable<String>
. It "emits events over time" as the user is typing in the text field. Now with some suitable chaining on that observable, the code will be able to, for example, filter an array of user objects to only those who have the search text in their name.
You see, searchTextField.rx.text
wasn't initialized with a value, it was initialized with a procedure that monitors the user's input into the text field.
Or another example:
let result = URLSession.shared.rx.data(request: URLRequest(url: URL(string: "http://myURL.com")!))
In the above, I'm initializing result
with a procedure which, when subscribed to, will make a network request and emit the result.