2014-03-13 7 views
5

나는 다음과 같은 시도없이 성공했다. -subscribeNext:을 사용하는 동등 물이 예상대로 작동합니다.중첩 가입없이 명령 실행 신호의 완료를 구독하려면 어떻게해야합니까?

// A 
[[_viewModel.loginCommand.executionSignals flatten] subscribeCompleted:^{ 
    NSLog(@"A"); 
}]; 
다음과 같이

내 유일한 작업 구현은 다음과 같습니다

// B 
[_viewModel.loginCommand.executionSignals subscribeNext:^(RACSignal *loginSignal) { 
    [loginSignal subscribeCompleted:^{ 
     NSLog(@"B"); 
    }]; 
}]; 

-flatten "A"의 작업, 어떻게 내가 중첩 구독을 사용하지 "B"를 다시 작성할 수 있습니까?

답변

10

-flatten 연산자는 모든 내부 신호가 완료된 경우에만 완료 신호를 반환하므로 외부 신호도 함께 완료해야합니다. -concat도 마찬가지입니다. 이 때문에 하나의 연산자를 적용하면 결과 신호에는 개별 완료가 표시되지 않고 최종 집계 완료 만 표시됩니다.

중첩 구독과 달리 내부 신호를 변환하여 완료를 나타내는 값을 보낼 수 있습니다. 이 일을하는 한 가지 방법은 -materialize 함께 : 그것은 RACCommand의 기본 직렬 실행의 의미를 일치하기 때문에 나는 -flatten 대신 -concat를 사용

[[[_viewModel.loginCommand.executionSignals 
    map:^(RACSignal *loginSignal) { 
     // Using -ignoreValues ensures only the completion event is sent. 
     return [[loginSignal ignoreValues] materialize]; 
    }] 
    concat] 
    subscribeNext:^(RACEvent *event) { 
     NSLog(@"Completed: %@", event); 
    }]; 

참고. 이 경우 궁극적으로는 -flatten이 동작을 -concat으로 축약합니다. 명령은 한 번에 하나씩 만 신호를 실행하기 때문입니다.

-materialize을 사용하는 것이 유일한 방법은 아니며, 완료를 나타내는 값을 전송하는 것이지만, 이는 유스 케이스에 대해 중요한 의미를 가진 값일 수 있습니다.

+2

이것은 꽤 일반적인 작업입니다 - 작업의 성공 확인을 보여줍니다. 예를 들어 메시지를 게시하고 싶습니다. 작업이 실패했거나 완료되었음을 알리는 메시지가 표시됩니다. 정말 더 명확하게 할 수있는 방법이 없습니까? 내 말은,이 접근법은 여전히 ​​중첩 된 executionSignal을 구독하는 것입니다. 명령에 둘 이상의 실행 신호가있는 경우 (예 :?) – Slabko

+2

'RACCommand'의'executionSignals'는 완료 이벤트를 직접 노출하지 않습니다.'materialize'를 사용하고 싶지 않다면, 또 다른 옵션은 "성공적인 완료"를 의미하는 의미있는 값을 사용하는 것입니다. 값을 보내지 않는 신호의 경우 완료를 나타내는 값을 보내고 무시하면됩니다. 네, 또 다른 옵션은'doCompleted :'연산자를 중첩 가입에 대한 대안으로 사용하는 것입니다. –

+2

기본적으로 RACCommand는 작업이 실패하거나 성공한 경우 추적하지 않습니다. 작업이 실행 중일 때와 실행 중이 아닌 경우에만 추적합니다. 내가 맞습니까? – Slabko

0

-executionSingals이 최소 한 번 이상 값을 보내고 실행 상태가 마지막으로 YES로 변경된 후에도 성공적으로 실행 상태가 NO로 변경되었다고 기술적으로 생각했습니다. 명령이 성공적으로 작업을 완료 할 때 -comleted이 전무를 전송 여기

@interface RACCommand (ARLCompletedSignal) 

@property (nonatomic, readonly) RACSignal *completed; 

@end 

:

#import "RACCommand+ARLCompletedSignal.h" 

@implementation RACCommand (ARLCompletedSignal) 

- (RACSignal *)completed 
{ 
    RACSignal *executing = self.executing; 
    RACSignal *signals = self.executionSignals; 
    RACSignal *errors = self.errors; 

    RACSignal *startingExecution = [RACSignal combineLatest:@[executing, [signals take:1]] 
                reduce:^id(NSNumber *executing, id _){ return executing; }]; 

    return [[startingExecution 
     ignore:@NO] 
     flattenMap:^RACStream *(id value) { 
      RACSignal *comletedOrFailed = [[executing ignore:@YES] subscribeOn:[RACScheduler scheduler]]; 
      return [[[comletedOrFailed take:1] takeUntil:errors] map:^id(id value) { return nil; }]; 
     }]; 
} 

@end 

헤더 : 이러한 생각을 바탕으로

나는 범주를했다. 또한 https://gist.github.com/slabko/546de430a16994a5da8e에서 작업이 성공적으로 완료되면 YES를 보내고 그렇지 않으면 NO를 보내는 버전을 찾을 수 있습니다.

나는 꽤 심플한 경우에 일부 시도해 보았습니다. 네가 할 수 없다면 나 한테 알려줘.

그러나 대부분의 경우 원래 신호의 완료에 동의하면 명령에 전달하기 전에 "해킹이없는"옵션으로 간주됩니다.