티스토리 뷰

반응형

 

안녕하세요 :) Zedd입니다.

Operator (1) - Mapping Elements

Operator (2) - Filtering Elements

 

3번째 Reducing Elements 섹션입니다. 

 

collect()

collect(_:)

collect(_:options:)

ignoreOutput()

reduce(_:_:)

tryReduce(_:_:)

 

오늘은 6개 밖에 안돼요!!!!

그 중 3개는 collect임

 

collect()

이 친구는 받은 모든 element를 수집(collect)하고, upstream publisher가 완료되면 collection의 single array를 내보내는 친구입니다.

그쵸. 10까지 땡 하고 나면 0부터 10까지의 배열을 만들어줍니다.

위 예제에서는 그냥 0부터 10까지였지만...이 요소가 무한대일 수 있어요.

그래서 collect는 그럴경우 걔네를 저장해야하니 메모리를 사용하게 됩니다.

즉, 매우 큰 element 집합에서는 시스템에 메모리 압력을 가할 수 있습니다. 주의해서 써야겠죠!?

 

collect(_:)

파라미터로 들어가는게 도대체 무었이냐

count입니다. 

걍 보면 감이 오죠..넣은 수만큼만 배열로 만들겠구나...

맞습니다. count에는 최대 수신 element 수를 넣으면 됩니다.

물론 5개를 요구했지만 1개가 나올 수 있습니다. 

 

예제로 봅시다.

자 아마도 

이렇게 있으면 결과는

[0, 1, 2, ,3, 4] 일거야! 라고 생각할 수 있는데, 

아닙니다!

결과는 

[0, 1, 2, 3, 4] [5, 6, 7, 8, 9] [10] 

가 나오게 됩니다. 

왜냐면 4하고 5가 publish될건데, collect의 count로 5를 줬으니 [0, 1, 2, 3, 4]에는 못들어가죠! 

그래서 5부터 배열이 새로 만들어지게 됩니다.

> collect(_:)는 .max(n)요소에 대한 요청을 받으면 upstream publisher에게  .max(count * n)을 요청한다고 합니다>?

 

collect(_:options:)

그렇다면 또 이건 뭘까...

파라미터로는 

strategy와 options이 들어갑니다. options는 기본적으로 nil이군요. 

strategy의 타입은 뭔 TimeGrouping이네요. 예제를 보는게 빠를 것 같습니다.

간단히 말해서 내가 지정한 Scheduler/Stride로 element 배열을 내보내는겁니다. 

Timer를 만들어줬죠. 1초마다 Date를 내놓을 것입니다. (Timer는 ConnectablePublisher라서 connect를 호출해줘야겠죠? 위에선 autoconnect를 씀)

그걸 내가 지정한 Scheduler/Stride에 맞춰서 배열을 만들어주면 됩니다. 저는 Stride로 5초를 줬네요. 

그럼 5초뒤에 print문이 찍힙니다. 5초뒤에 Timer가 멈추는거 아니잔슴? 계속 5초간격으로 배열이 만들어지게 됩니다. 

그럼 strategy에 뭐가 들어갈 수 있는지 봅시다./

이렇게 2가지가 들어갈 수 있네요.

내 Xcode가 꼬진건가..? 자동완성 안됨ㅋ

암튼..둘 다 Context와 Stride를 받네요.

Context는 보시다시피 Scheduler타입입니다. 즉..Scheduler를 채택하는 모든 타입이 들어갈 수 있다?!?!? 뿌슝빠슝

예제에서는 RunLoop를 넣어줬는데 뭐 DispatchQueue.global()이런거 넣어줘도 되구요..다 됨 

그리고 Stride는 second, milliseconds등등이 들어갈 수 있습니다.

이 stride가 끝나면 publisher는 수집한 element의 배열을 내보내게 됩니다.

byTime을 봤으니 byTimeOrCount를 보도록 합시다. 다 똑같고 끝에 Int만 받네요. 

collect(_:)에서 본 그거 맞습니다..!

제가 Timer의 stride를 1에서 0.1로 바꾸겠습니다. 그럼 0.1초마다 Date를 방출할거고, 현재 Stride는 5니까 배열에 요소수가 조금 많아지겠네요 그렇죠?

네 많네요. 그럼 byTimeOrCount를 써봅시다.

그리고 5를 주겠습니다.

그럼 배열의 최대 요소 수가 5개로 되어서 나오겠죠? Timer가 0.1초마다 동작하니까 5개가 0.5초만에 채워질겁니다. 

이해가셨나요..? 

collect(_:options:)는 이대로 끝이 아닙니다..

바로 option을 받을 수 있었죠. 기본값은 nil입니다

이 옵션의 특징은 Scheduler의 옵션을 따릅니다. 

Strategy의 Scheduler로 

이런것들을 넣을 수 있잖아요? 옵션은 각 Scheduler의 옵션이 나타나게 됩니다.

제가 만약 RunLoop를 넣었다고 칩시다.  

이렇게요.

그럼 옵션은

이런것들을 넣을 수 있습니다. 보면, RunLoop.SchedulerOptions를 넣을 수 있죠. 그럼 제가 DispatchQueue를 넣으면?

DispatchQueue의 SchedulerOptions을 넣을 수 있게 됩니다. 각자 자기가 지정한 SchedulerOptions을 하고싶은대로 넣으면 됩니다.

QoS지정해봐야 뭐 별 의미 없을 것 같아서 하진 않을게요~

 

ignoreOutput()

무시하다 / 출력을 

ㅇㅋ

자 간단한 예제입니다. 업스트림 요소들을 전부 받으니 sink에서 요소들이 전부 출력되겠죠.

하지만 ignoreOutput은 닉값을 한답니다.

모든 업스트림 요소를 받아들이지만, 요소를 전부 무시하고 완료, 실패의 completion상태만 전달하게 됩니다. 

물론 에러가 나면 스트림이 종료되고 실패로 떨어지겠죠?!?!

 

reduce(_:_:)

어이어이 reduce..

reduce는 스트림의 각 element를 collects(수집)하고 완료시 최종 결과만 publish합니다. 

제가 mapping elements글에서 scan볼 때 reduce를 잠깐 언급했는데, 기억하시나요!?

scan을 잠깐 봅시다.

scan은  operation의 과정에서 생긴 값들을 계속 publish한다고 그랬는데요! 

reduce는 이 과정들을 전부 publish하는게 아니라, 최종값만 publish합니다.

이렇게요! 

 

tryReduce(_:_:)

scan도 tryScan이 있었듯...reduce도 tryReduce가 있다?!?!? 뿌슝빠슝

tryScan예제에서 조금 변경했어요. tryScan때는

"11 6 3 1 1 failure(__lldb_expr_49.DivisionByZeroError())" 이런 결과가 나왔었는데,  tryReduce에서는 마지막 최종값만 publish하니까..

근데 그 도중 에러가 생겼으니 "failure(__lldb_expr_51.DivisionByZeroError())" 딱 이렇게만 결과가 나올거에요. 

그게 싫으니 replaceError로 에러를 0으로 바꿔봤어요.( .catch({ _ in Just(0) }) 이런식으로 해도 됨.)

그래서 결과가 "0 finished"로 나온것을 볼 수 있습니다. 

 

 

이해가셨나요!? 전 헷갈리면서도..헷갈리지 않으면서도...헷갈ㄹ...

얼른 Operator공뷰ㅜ를 끝내고 싶네요.

 

다음 글 읽으러가기

 

Combine ) Operator (4) - Applying Mathematical Operations on Elements

안녕하세요 :) Zedd입니다. 오늘은 Combine 4번째 시간~ Applying Mathematical Operations on Elements 섹션입니다. 뭔가 수학적인 오퍼레이션을 적용하는...Operator같네요. count max max(by:) tryMax(by:)..

zeddios.tistory.com

 

반응형