2013-11-28 44 views
6

我正在實施我的第一個代碼https://github.com/ReactiveCocoa/ReactiveCocoa爲什麼在ReactiveCocoa中調用信號兩次?

用於登錄用戶。行[subscriber sendNext:user];被調用兩次,但我希望只有一個。和地圖是不是在所有所謂的(所以自動登錄不會被調用)

這是我實現:

-(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; 
} 

正所謂是這樣的:

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

單步執行代碼並查看發生了什麼。或者在進入sendNext時設置一個斷點,並在每次調用時檢查調用堆棧。 –

回答

9

這是因爲該塊傳遞到+[RACSignal createSignal:]執行每當訂閱的信號是由,和你的代碼創建兩個單獨訂閱:

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

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

如果你只是想創建一個訂閱,使用方法-[RACSignal subscribeError:completed:]

[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

雖然有時this solution可能是你所需要的,有時你想確保訂閱塊只調用一次,也許是因爲它會產生副作用。在這種情況下,您可以返回調用-replay信號:

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]; 

這個新的,導出的信號將在相同的消息或錯誤發送給所有用戶。如果信號完成,並且有新的用戶,它也會立即收到所有消息。

相關問題