iosswiftreactive-cocoareactive-cocoa-4

rac_command only responds to single click


I am trying to detect clicks on an UIElement like a button using Reactive Cocoa, using RAC for the first time in MVVM architecture.

I set the rac_command for my button in my ViewController.

    addContactBtn.rac_command = viewModel.addContact

My ViewModel does the following:

func init(){
self.addContact = RACCommand() {
  (any:AnyObject!) -> RACSignal in
  return RACSignal.createSignal({
    (subscriber: RACSubscriber!) -> RACDisposable! in
    print("creating viewModel")
    let viewModel = ContactAddViewModel(services: self.services)
    self.services.pushViewModel(viewModel)

    return RACDisposable(block: {
    })
  })
}
}

However, the command is executed only once and then the button is in disabled state when I pop the view controller and come back to original viewController. How can detect the button click any number of times?


Solution

  • Obviously, you missed something and had a simple mistake.

    RACCommand expects to a signal which will be alive when the button clicked and be disposed after click-business-logic (like create viewModel, then pushViewModel in the above) executed. That is to say each button clicking-event associates a signal, not shares one unique signal, but has common signal inner logic. If a signal does not achieve completion or error, the responding clicking-event is not finished such that the button is disabled.

    The below modified codes could be correct.

    func init(){
        self.addContact = RACCommand() {
            (any:AnyObject!) -> RACSignal in
            return RACSignal.createSignal({
                (subscriber: RACSubscriber!) -> RACDisposable! in
                print("creating viewModel")
                let viewModel = ContactAddViewModel(services: self.services)
                self.services.pushViewModel(viewModel)
    
                // if you like to expose some value
                // subscriber.sendNext(value)
    
                subscriber.sendCompleted()  // which makes clicking-event finished
    
                // maybe error occurs
                // subscriber.sendError()
    
                return RACDisposable(block: {
                })
            })
        }
    }
    

    I would like to advise you to checkout CocoaAction and Action in ReactiveSwift, which are replacement for RACCommand of legacy ReactiveObjC.