ios - ReactiveCocoa subscribeCompleted in command never executes -


i new reactivecocoa , mvvm. trying simple login screen. view controller in storyboard has 2 textfields (username, password) , 1 button. when button clicked should send post request username , password server , receive secure token. when response received, should execute sendcompleted. subscribecompleted in raccommand executionsignals block never gets executed , can't go next screen.

viewcontroller.m

//  viewcontroller.m  #import "viewcontroller.h" #import <reactivecocoa/reactivecocoa.h> #import <reactivecocoa/racextscope.h> #import "viewmodel.h"  @interface viewcontroller ()  @property (strong, nonatomic) viewmodel *viewmodel;  @property (weak, nonatomic) iboutlet uibutton *button; @property (weak, nonatomic) iboutlet uitextfield *usernametextfield; @property (weak, nonatomic) iboutlet uitextfield *passwordtextfield; @end  @implementation viewcontroller  - (instancetype)initwithcoder:(nscoder *)adecoder {     self = [super initwithcoder:adecoder];     if (!self) return nil;      _viewmodel = [viewmodel new];      return self; }  - (void)viewdidload {     [super viewdidload];      // reactive stuff     rac(self.viewmodel, username) = self.usernametextfield.rac_textsignal;     rac(self.viewmodel, password) = self.passwordtextfield.rac_textsignal;     self.button.rac_command = self.viewmodel.logincommand;      @weakify(self);     // logged in     [[[[self.viewmodel.logincommand.executionsignals logall] flattenmap:^racstream *(racsignal *execution) { // don't understand part well. flattenmap in particular example?         return [execution ignorevalues]; // assume should ignore sendnext:     }] subscribecompleted:^{         nslog(@"completed"); // subscribecompleted block never called!          //[self performseguewithidentifier:@"nextscreen" sender:nil]; go next screen or similar     }];       // error occured during login     [self.viewmodel.logincommand.errors subscribenext:^(id error) { // works fine.         nslog(@"login error: %@", error);         // show alert view     }]; }  @end 

viewmodel.h

//  viewmodel.h  #import <foundation/foundation.h> @class raccommand;  @interface viewmodel : nsobject  @property (nonatomic, readonly) raccommand *logincommand; @property (strong, nonatomic) nsstring *username; @property (strong, nonatomic) nsstring *password;  @property (nonatomic, readonly, getter=isloading) bool loading; // used loading indicatior view.  @end 

viewmodel.m

//  viewmodel.m   #import "viewmodel.h" #import <reactivecocoa/reactivecocoa.h> #import <reactivecocoa/racextscope.h>  @interface viewmodel ()  @property (strong, nonatomic) raccommand *logincommand; @property (nonatomic, assign, getter=isloading) bool loading;  @end  @implementation viewmodel  // initializer - (instancetype)init {     self = [super init];     if (!self) return nil;      _networkmanager = [networkmanager shared];      return self; }  // getter - (raccommand*)logincommand {     if (_logincommand) {         _logincommand = [[raccommand alloc]initwithenabled:[self validatelogininputs] signalblock:^racsignal *(id input) {             return [self loginusersignal];         }];     }     return _logincommand; }  // methods - (racsignal*)validatelogininputs {     return [racsignal combinelatest:@[racobserve(self, username), racobserve(self, password)]                              reduce:^id(nsstring *username, nsstring *password) {                                  return @(username.length > 0 && password.length > 0);                              }]; }   - (racsignal*)loginusersignal {     @weakify(self);     return [[[[racsignal createsignal:^racdisposable *(id<racsubscriber> subscriber) {          @strongify(self);         self.loading = yes;         [self.networkmanager validateloginwithusername:self.username                                               password:self.password                                                success:^(nsdictionary *jsonresponse) {                                                    [subscriber sendnext:jsonresponse];                                                    [subscriber sendcompleted]; // doesnt work                                                } failure:^(nserror *error) {                                                    [subscriber senderror:error]; // works                                                }];     }] donext:^(id x) {;         // save secure token memory      }] finally:^{         // when error occurs or complete, stop animation spinner.         @strongify(self);         self.loading = no;     }]             replaylazily];   } 

update

i did this:

[self.viewmodel.logincommand.executionsignals subscribenext:^(id signal) {        [signal subscribenext:^(id x) {            nslog(@"logged in successfully");            // [self perfromseguewithidentifier:@"setpin" sender:nil];        }];     }]; 

but don't think clean solution.

self.viewmodel.logincommand.executionsignals - not send "completed"

viewmodel.h

@property (nonatomic, strong, readonly) racsignal *completed; 

viewmodel.m

self = [super init];     if (self) {          racsubject *completed = [racsubject subject];         _completed = completed;  [[[self.logincommand.executionsignals map:^id(racsignal *value) {             return [value docompleted:^{                 [completed sendcompleted];             }];         }] switchtolatest]         subscribenext:^(id x) {         }];      return self; } 

Comments

Popular posts from this blog

ruby on rails - RuntimeError: Circular dependency detected while autoloading constant - ActiveAdmin.register Role -

c++ - OpenMP unpredictable overhead -

javascript - Wordpress slider, not displayed 100% width -