2
votes

How do I implement an event emitter using RxSwift? (An object that can emit data that is consumed by other objects that are subscribed to it.)

After going through the Rx docs and examples, I feel like a complete idiot and am still extremely confused on how to manually emit events from Observers to Observables. My understanding that we have some Observable that can emit events with data to all Observers that are subscribed to that Observable. However, I have zero idea on how this is actually implemented in Swift.

Here's an example of something I'm trying to implement:

class VendingMachine {

    let dispenser = Observable<Drink>

    // Notify all subscribed Observers that this machine dispensed a drink.
    func dispenseDrink(item: Drink) {
        dispenser.onNext(item)
    }

}

And a second file:

class MachineReporter: Observer {

    let dispenser = VendingMachine().dispenser

    init() {
        dispenser.subscribe(self)
    }

    onNext { drink in
        print("Vending machine dispensed a drink: \(drink)"
    }

}

My brain is fried. I'm just going to switch to a specialized library like EmitterKit for now because I'm clearly misunderstanding how this works.

But I need to figure out how Rx works or I will go crazy. Help!

2

2 Answers

4
votes

I'm pretty confused about what you're planning on doing with MachineReporter, so my code just addresses making it work, although it may not be very useful.

I would highly suggest you go through the RxSwift Playground examples and make sure you feel comfortable with those. Your question in particular deals with Subjects. That should get you over the initial "hump" of uncomfortability and frustration. I definitely hear you about that though, it's a different way of thinking, but it's completely worth pushing past that first hurdle. Stick with it.

class VendingMachine {

    let dispenser = PublishSubject<Drink>()

    func dispenseDrink(item: Drink) {
        dispenser.onNext(item)
    }
}

class MachineReporter {

    let disposeBag = DisposeBag()
    let dispenser = VendingMachine().dispenser

    init() {
        dispenser.asObservable()
            .subscribeNext { drink in
                print("Vending machine dispensed a drink: \(drink)")
            }
            .addDisposableTo(disposeBag)
    }
}
1
votes

Should use a Subject for this.

A Subject is a special form of an Observable Sequence, you can subscribe to and add elements to it. There are 4 kinds of Subjects in RxSwift

http://reactivex.io/documentation/subject.html

I would recommend starting off using a PublishSubject here.

let observable = PublishSubject<SomeTypeOrEvent>()

observable.subscribe(onNext: { (SomeTypeOrEvent) in 
    self.doSomethingWithEvent(something: SomeTypeOrEvent) 
}).addDisposableTo(disposeBag)

...

// emits some type/event
observerable.onNext(SomeTypeOrEvent)