cozzin
코찐 기술 블로그
cozzin
전체 방문자
오늘
어제
  • 분류 전체보기
    • Kotlin
    • 백엔드
    • iOS
      • Swift
      • SwiftUI
      • Combine
      • Architecture
    • 개발환경
    • 세미나
    • 생각정리
    • 스터디
    • CS
      • Refactoring
      • OS

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • LinkedIn
  • 강의

공지사항

인기 글

태그

  • 디자인패턴
  • SwiftUI
  • 워닝제거
  • 운영체제
  • 컴퓨터공학
  • Warning
  • slide-over
  • multicast
  • Swift
  • ios
  • Ribs
  • WWDC
  • CS
  • os
  • darkmode
  • WWDC21
  • XCode
  • Combine
  • 테스트
  • 리팩토링

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
cozzin

코찐 기술 블로그

[Combine 책 정리] Chapter 7: Sequence Operators
iOS/Combine

[Combine 책 정리] Chapter 7: Sequence Operators

2021. 1. 22. 23:26
반응형

안녕하세요 코찐입니다.

아래의 자료를 따라서 공부하고 있습니다.

https://www.raywenderlich.com/books/combine-asynchronous-programming-with-swift/v2.0

Finding values

min

  • greedy: publisher가 finsih될 때 까지 기다림
[1, -50, 246, 0].publisher.min() // -50

value가 Comparable을 준수하지 않는다면?

Comparable을 준수하지 않는 객체가 있으면 비교문을 직접 넣어서 min을 사용할 수 있다.
아래 예제에서는 억지로 Comparable을 준수하지 않도록 만든 다음 min을 찾도록 해보는 것. 조금 억지지만 이렇게 하면 결과값에서 다시 String으로 변환해서 체크해볼 수 있다.

["12345", "ab", "hello world"]
    .compactMap { $0.data(using: .utf8) } // [Data]
    .publisher
    .min(by: { $0.count < $1.count })

max

  • greedy: publisher가 finsih될 때 까지 기다림
["A", "F", "Z", "E"].publisher.max() // Z

first

  • lazy: 첫번째 값을 만나면 값 방출 후 finish

["A", "B", "C"].publisher.first() // A

first(where:)

이건 앞서 first() 보다 더 많이 쓸 것 같음
단순히 제일 처음에 오는 value 보다 매칭되는 첫번째 값을 받아보는게 더 유용해 보임

["J", "O", "H", "N"]
    .first(where: { "Hello World".contains($0) })

last

  • completion .finish 이후에 값 방출
["A", "B", "C"].publisher.last() // C

output(at:)

  • index 번째의 value를 방출함.
  • 특정 index의 value를 찾는거라서 1개씩 request 함. 이게 어떤 의미인지 정확하게는 모르겠음
let publisher = ["A", "B", "C", "D"].publisher

publisher
    .print("publisher")
    .output(at: 2)
    .sink(receiveValue: { print("Value at index 2 is \($0)") })
    .store(in: &subscriptions)
publisher: receive subscription: (["A", "B", "C", "D"])
publisher: request unlimited
publisher: receive value: (A)
publisher: request max: (1) (synchronous) // Demand.max(1)
publisher: receive value: (B)
publisher: request max: (1) (synchronous) // Demand.max(1)
publisher: receive value: (C)
Value at index 2 is C
publisher: receive cancel

output(in:)

  • 특정 index 범위 안의 값들을 방출함
["A", "B", "C", "D", "E"].publisher
    .output(in: 1...3) // 1, 2, 3 각각 방출함

Querying the publisher

count

finsih 후에 몇 개의 value를 받았는지 방출함

let publisher = ["A", "B", "C"].publisher

publisher
    .print("publisher")
    .count()
    .sink(receiveValue: { print("I have \($0) items") }) // 3
    .store(in: &subscriptions)

contains

만족하는 값 있으면 ture/false 방출하고 종료됨

let publisher = ["A", "B", "C", "D", "E"].publisher
let letter = "C"

publisher
    .print("publisher")
    .contains(letter)
    .sink(receiveValue: { contains in
        print(contains ? "Publisher emitted \(letter)!" : "Publisher never emitted \(letter)!")
    })
    .store(in: &subscriptions)
publisher: receive subscription: (["A", "B", "C", "D", "E"])
publisher: request unlimited
publisher: receive value: (A)
publisher: receive value: (B)
publisher: receive value: (C)
publisher: receive cancel
Publisher emitted C!
  1. C 까지 검사하고
  2. 조건 만족해서 cancel
  3. true 방출

여기서 letter = "F" 였다면

  1. E 까지 전부 검사하고
  2. finish
  3. false 방출

contains(where:)

let people = [
    (456, "Scott Gardner"),
    (123, "Shai Mishali"),
    (777, "Marin Todorv"),
    (214, "Florent Pillet")
]
.map(Person.init)
.publisher

people
    .contains(where: { $0.id == 800 || $0.name == "Marin Todorv"}) // 이런식으로 조건문 작성
    .sink(receiveValue: { contains in
        print(contains ? "Criteria matches!" : "Couldn't find a match for the criteria")
    })
    .store(in: &subscriptions)

allSatisfy

  1. 모든 value가 조건을 만족하는지 체크
  2. 중간에 하나라도 만족하지 않으면 .cancel / 전부다 만족하면 .finsih
  3. 결과(Bool) 방출
let publisher = stride(from: 0, to: 5, by: 2).publisher

publisher
    .print("publisher")
    .allSatisfy { $0 % 2 == 0 }
    .sink(receiveValue: { allEven in
        print(allEven ? "All numbers are even" : "Something is odd...")
    })
    .store(in: &subscriptions)
publisher: receive subscription: (Sequence)
publisher: request unlimited
publisher: receive value: (0)
publisher: receive value: (2)
publisher: receive value: (4)
publisher: receive finished
All numbers are even

reduce

upstream의 값을 누산(accumulate)해서 complete시에 값을 방출함

let publisher = ["Hel", "lo", "Wor", "ld", "!"].publisher

publisher
    .print("publisher")
    .reduce("") { accumulator, value in
        accumulator + value
    } // .reduce("", +) 이렇게도 표현 가능
    .sink(receiveValue: { print("Reduced into: \($0)") })
    .store(in: &subscriptions)
publisher: receive subscription: (["Hel", "lo", "Wor", "ld", "!"])
publisher: request unlimited
publisher: receive value: (Hel)
publisher: receive value: (lo)
publisher: receive value: (Wor)
publisher: receive value: (ld)
publisher: receive value: (!)
publisher: receive finished
Reduced into: HelloWorld!

scan과 reduce가 다른점

  • scan은 누산된 값을 매번 방출함
  • reduce는 complete 되고 누산된 값을 방출함

 

이 책에 있는 Operator들을 다 배웠습니다 🎉 🎉

다음 챕터는 실습!!

반응형
저작자표시 (새창열림)

'iOS > Combine' 카테고리의 다른 글

[Combine 책 정리] Chapter 10: Debugging  (0) 2021.01.27
[Combine 책 정리] Chapter 9: Networking  (0) 2021.01.27
[Combine 책 정리] Chapter 6: Time Manipulation Operators  (0) 2021.01.19
[Combine 책 정리] Chapter 5: Combining Operators  (0) 2021.01.18
[Combine 책 정리] Chapter 4: Filtering Operators  (0) 2021.01.13
    'iOS/Combine' 카테고리의 다른 글
    • [Combine 책 정리] Chapter 10: Debugging
    • [Combine 책 정리] Chapter 9: Networking
    • [Combine 책 정리] Chapter 6: Time Manipulation Operators
    • [Combine 책 정리] Chapter 5: Combining Operators
    cozzin
    cozzin
    Software Engineer

    티스토리툴바