2013-11-28 4 views
6

https://github.com/ReactiveCocoa/ReactiveCocoa으로 첫 코드를 구현하고 있습니다.ReactiveCocoa에서 신호가 두 번 호출되는 이유는 무엇입니까?

사용자를위한 로그인입니다. 줄 [subscriber sendNext:user];이 두 번 호출되지만, 나는 단 하나 일 것으로 기대합니다. 블록이에 전달하기 때문에이 문제가 발생

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 *) 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; 
} 

이 방법으로 호출됩니다 (자동 로그인이 호출되지 않도록) 그리고지도가 전혀 호출되지 않습니다이 내 구현

입니다 +[RACSignal createSignal:]은 신호 구독이 이루어질 때마다 실행되며 코드는 2 개의 개별 구독을 만듭니다.

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

. 신호가 완료되고 새 가입자가있는 경우 즉시 모든 메시지가 수신됩니다.

관련 문제