1

I'm trying to implement user-driven refreshing in my Rx based networking code, and my current design is as follows:

  1. Create a sink that has Void values passed into it every time the user initiates a refresh action
  2. flatMap the latest .Next event on that sink's Observable into a new network call
  3. Transform the network response into a new view model and pass that back into the view controller

The part I'm getting hung up on is how to create a sink for those events to go down. My current code is as follows:

func contactListModel() -> Observable<ContactListViewModel<Contact>> {
    // Create a sink for refresh events
    var refreshSink: AnyObserver<Void> = AnyObserver { event in }
    let refreshObservable = Observable<Void>.create { observer in
        refreshSink = observer
        return NopDisposable.instance
    }

    // Define action handlers
    let searchClosure = { (query: String?) in
        self.contactsSearchTerm.value = query
    }
    let refreshClosure = refreshSink.onNext

    // TODO: [RP] Make contact list view controller handle a nil view model to remove the need for this code
    let initialViewModel = ContactListViewModel<Contact>(contacts: [], searchClosure: searchClosure, refreshClosure: refreshClosure)

    // Perform an initial refresh
    defer {
        refreshSink.onNext()
    }

    // Set up subscription to push a new view model each refresh
    return refreshObservable
        .flatMapLatest {
            return self.networking.request(.ListContacts)
        }
        .mapToObject(ListContactsResponse)
        .map { response in
            return ContactListViewModel(contacts: response.contacts, searchClosure: searchClosure, refreshClosure: refreshClosure)
        }
        .startWith(initialViewModel)
}

Now it's obvious why my code to create an event sink doesn't work here. The block being passed into refreshObservable's create method is only called once the observer is subscribed to, so the refreshSink won't be reassigned until then. Furthermore, if this observable is subscribed to more than once, the refreshSink variable will be reassigned.

So my question is this: how do I create an Observable that I can manually push events down? Or alternatively, is there a better design I could be using here?

I know ReactiveCocoa has the pipe static method on Signal that will do something like what I'm looking for, but I've found no equivalent in the Rx API.

rpowell
  • 1,464
  • 2
  • 16
  • 29

0 Answers0