2013-11-28 6 views
6

İlk kodumu https://github.com/ReactiveCocoa/ReactiveCocoa ile uygulıyorum.ReactiveCocoa'da neden sinyal iki kez çağrılır?

Kullanıcı girişi için kullanılır. [subscriber sendNext:user]; hattı iki kez çağrılır, ancak sadece bir tane olmasını beklerim. Blok geçirilen Bunun nedeni

NSString *email = data[@"email"]; 
NSString *pwd = data[@"pwd"]; 
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack]; 

RACSignal *login = [[SyncEngine server] login:email pwd:pwd]; 

[login 
subscribeCompleted:^ 
{ 
    [[NSNotificationCenter defaultCenter] 
    postNotificationName:NOTIFY_LOGIN_CHANGED 
    object:self]; 

    [SVProgressHUD showSuccessWithStatus:LOC_OK]; 


    [self cancelForm]; 
}]; 

[login 
subscribeError:^(NSError *error) 
{ 
    [SVProgressHUD dismiss]; 

    [AppUrls alertError:LOC_ERROR_LOGING msg:error.userInfo[@"error"]]; 
}]; 
+0

Koddan tek adımla geçin ve neler olduğunu görün. Ya da, her gönderiminde, gönderim sırasına göre bir kesme noktası ayarlayın ve çağrı yığınını inceleyin. –

cevap

9

:

-(RACSignal *) login:(NSString *)email pwd:(NSString *)pwd 
{ 
    DDLogInfo(@"Login user %@", email); 

    RACSignal *login = [RACSignal createSignal:^ RACDisposable *(id<RACSubscriber> subscriber) 
    {   
     [PFUser logInWithUsernameInBackground:email password:pwd block:^(PFUser *user, NSError *error) { 

      if (error) { 
       [subscriber sendError:error]; 
      } else { 
       [subscriber sendNext:user]; 

       [subscriber sendCompleted]; 
      } 
     }]; 

     return nil; 
    }]; 

    [login map:^(PFUser *user) { 
     return [self autoLogin:user]; 
    }]; 

    return login; 
} 

bu şekilde deniliyor: (autologin asla denir böylece) ve harita hiç çağrılmaz Bu benim uygulaması

olduğunu +[RACSignal createSignal:], bir sinyale her abone yapıldığında yürütülür ve kodunuz iki ayrı abonelik oluşturur:

[login subscribeCompleted:^{ ... }]; 

[login subscribeError:^(NSError *error) { ... }]; 

Yalnızca tek bir abonelik oluşturmak istiyorsanız, yöntem -[RACSignal subscribeError:completed:] kullanın:

[login subscribeError:^(NSError *error) { 
     [SVProgressHUD dismiss]; 

     [AppUrls alertError:LOC_ERROR_LOGING msg:error.userInfo[@"error"]]; 
    } 
    completed:^{ 
     [[NSNotificationCenter defaultCenter] 
     postNotificationName:NOTIFY_LOGIN_CHANGED 
     object:self]; 

     [SVProgressHUD showSuccessWithStatus:LOC_OK]; 


     [self cancelForm]; 
    }]; 
5

bazen this solution tek ihtiyacınız olabilir de, bazen abonelik bloğu sadece belki bir kez denir emin olmak istiyoruz yan etkiler üretir. Bu durumda, -replay arayarak sinyali dönebilirsiniz: Bu yeni ve türetilmiş sinyalin tüm abonelere aynı mesaj veya hatayı gönderecek

return [[RACSignal createSignal:^ RACDisposable *(id<RACSubscriber> subscriber) {   
    [PFUser logInWithUsernameInBackground:email password:pwd block:^(PFUser *user, NSError *error) { 

     if (error) { 
      [subscriber sendError:error]; 
     } else { 
      [subscriber sendNext:user]; 

      [subscriber sendCompleted]; 
     } 
    }]; 

    return nil; 
}] map:^(PFUser *user) { 
    return [self autoLogin:user]; 
}] replay]; 

. Sinyal tamamlanırsa ve yeni bir abone varsa, bu hemen tüm mesajları alır.