Gerardo Navarro Suarez
Gerardo Navarro Suarez

Reputation: 423

How to observe method invocation in ViewModel?

I'm new to ReactiveCocoa. In my Swift ViewController, I'd like to observe/listen to the invocation of the following method in the RecipeSwipingViewModel:

func fillSwipingQueueWith(recipeSwipingCards: [RecipeSwipingCardVM]) { ... }

Unfortunately, I cannot get this to work, although I guess it is a pretty common use case. I tried several variations of this:

self.viewModel.rac_signalForSelector("fillSwipingQueueWith")...
self.viewModel.rac_signalForSelector("fillSwipingQueueWith:")...
self.viewModel.rac_signalForSelector(Selector("fillSwipingQueueWith:"))...
self.viewModel.rac_signalForSelector("fillSwipingQueueWith:", fromProtocol:NSProtocolFromString("RecipeSwipingViewModel")...

What am I missing? Is it actually possible to listen to the method invocation inside another object (without a protocol)? Help is highly appreciated.

Cheers, Gerardo

Upvotes: 2

Views: 536

Answers (1)

Cosyn
Cosyn

Reputation: 5007

rac_signalForSelector is implemented by Objective-C runtime features. To make it work in Swift, you must mark your method as dynamic:

dynamic func fillSwipingQueueWith(recipeSwipingCards: [RecipeSwipingCardVM])

Then a rac_signalForSelector("fillSwipingQueueWith:") signal should send corretly.

Note, this is impossible if the method is a pure Swift function (e.g. it takes a Swift struct argument) or if the class of the method doesn't inherit from NSObject. The Swift way of observing method invocation is making the signal explicit. For example:

class ViewModel {
    let (callSignal, callObserver) = Signal<[RecipeSwipingCardVM], NoError>.pipe()

    func fillSwipingQueueWith(recipeSwipingCards: [RecipeSwipingCardVM]) {
        // function implementation

        callObserver.sendNext(recipeSwipingCards)
    }
}

self.viewModel.callSignal.observeNext { recipeSwipingCards in
    print("method call")
}

Upvotes: 1

Related Questions