How to observe array property changes in RxSwift
Most of the time, if you have control of the backing variable, you would prefer Variable
to using rx_observe
.
class ViewController: UIViewController {
var myArray : Variable<NSArray>!
}
The first time you'll use myArray, you would asign it like so
myArray = Variable(["a"])
Then, if you want to change its value
myArray.value = ["b"]
And you can easily observe its changes, using
myArray.asObservable().subscribeNext { value in
// ...
}
If you really want to use rx_observe
(maybe because the variable is used elsewhere in your program and you don't want to change the API of your view controller), you would need to declare myArray
as dynamic
(another requirement is that the hosting class is a child of NSObject
, here UIViewController
satisfies this requirement). KVO is not implemented by default in swift, and using dynamic ensures access is done using the objective-c runtime, where KVO events are handled.
class ViewController: UIViewController {
dynamic var myArray: NSArray!
}
Documentation for this can be found here
How to subscribe on array changes using RxSwift?
In order to observe changes for your similarObjects , you have to make it of type Observable...
So for example you declare similarObjects as follow:
var similarObjects: PublishSubject<[Objects]> = PublishSubject<[Objects]>()
And you can subscribe to it by:
similarObjects
.asObservable()
.subscribe(onNext:{
print($0)
}
And when you want to assign it a value, you can use onNext operator
Example:
similarObjects.onNext(someArray)
By calling onNext, print($0) statement will be executed, make sure to subscribe before calling onNext to your Subject..
Observe changes in any property of any member of an array
You need to add the observer
to all the Apple
objects that you're adding in apples
array
.
First of all create a property named observers
of type [NSKeyValueObservation]
at class level, i.e.
var observers = [NSKeyValueObservation]()
Now, create a method that will append new Apple
instances in apples array
and add observer
to it,
func addNewApple(_ apple: Apple) {
observers.append(apple.observe(\.color, options: [.new], changeHandler: { (apple, changes) in
if let newValue = changes.newValue {
print(newValue)
}
}))
apples.append(apple)
}
To observe a property of an object, that must be marked it @objc dynamic
. So, the Apple
definition goes like,
class Apple: NSObject {
@objc dynamic var color = "Red"
}
Now, you can use it as described below,
let myApple = Apple()
self.addNewApple(myApple)
myApple.color = "Blue"
Combining all the bits and pieces, the whole code can be written like,
class VC: UIViewController { var apples = [Apple]() var observers = [NSKeyValueObservation]()
override func viewDidLoad() { super.viewDidLoad() let myApple = Apple() self.addNewApple(myApple) myApple.color = "Blue" let otherApple = Apple() otherApple.color = "Green" } func addNewApple(_ apple: Apple) { observers.append(apple.observe(\.color, options: [.new], changeHandler: { (apple, changes) in if let newValue = changes.newValue { print(newValue) } })) apples.append(apple) }}
How to observe object's property in RxSwift?
Actually you should declare currentTemperature
as Variable
to observe the value changes. Your Forecast
will become as this
class Forecast {
let city: City
var currentTemperature: Variable<String> = Variable("0")
init(city: City) {
self.city = city
}
func loadForecast() {
self.currentTemperature.value = "+10"
}
}
So now you can subscribe to listen the changes in currentTemperature
as below,
class ForecastViewModel {
fileprivate let variableForecast: Variable<Forecast>
var navigationTitle: Observable<String> {
return Observable.just("No name")
}
init(forecast aForecast: Forecast) {
self.variableForecast = Variable(aForecast)
self.variableForecast.value.currentTemperature.asObservable().subscribe(onNext: { (value) in
print(value)
})
variableForecast.value.currentTemperature.value = "-15"
variableForecast.value.loadForecast()
}
}
RxSwift : Observe each element observable property in observable array
You can use Observable.combineLatest to combine all latest event in array's element's property
Here is the solution that worked for me.
class Player {
let stamina = Variable(0)
}
// ViewController
let disposeBag = DisposeBag()
// Array
let playerList: Variable<[Player]> = Variable([])
// Observing each player stamina at once
playerList.asObservable()
.flatMapLatest { players -> Observable<[Int]> in
let playerStaminaObservableList = players.map { $0.stamina.asObservable() }
return Observable.combineLatest { playerStaminaObservableList }
}
.subscribe(onNext: {
print("List of playerStamina: \($0)")
})
.disposed(by: disposeBag)
Feel free to correct any mistake.
In RxCocoa/RxSwift, how to observe BehaviorRelay[object] array size changed
From documentation:
- parameter comparer: Equality comparer for computed key values.
I believe you should check the Equality with ==
operator. So, in your case, try this way:
BehaviorRelay<[object]>
.asObservable()
.distinctUntilChanged{ $0.count == $1.count}
.subscribe{....}
Related Topics
Best Way to Handle Errors from Async Closures in Swift 2
How to Record My MAC's Internal Sound, Not the Microphone!, Using Avcapturesession
Binding 2 Properties (Observe) Using Keypath
In What Situation Would One Use Expectationfornotification in Swift Testing
Programmatically Create an Nsviewcontroller Without an Xib in Swift 3
How to Set Realtime Thread in Swift
In Swift, Can You Find All Types in a Module That Adhere to a Specific Protocol
Anonymous User in Realm Mobile Platform
What Is Existentialmetatype in Swift
How to Simplify Swift Enum Custom Init
Using Structs (Bytes) with Swift - Struct to Nsdata and Nsdata to Struct
Converting Audiobuffer to Cmsamplebuffer with Accurate Cmtime
How to Use a Value Type Object as a Reference Type
Swift Packages and Conflicting Dependencies
Refreshing Auth Token with Moya
Nsposixerrordomain When Binding to Socket on MACos 10.12
Passing Arguments to #Selector Method in Swift
How to Check the Type of a Variable Against Another Variable in Swift