728x90
Operator
: Publisher가 subcriber에게 전달하는 데이터를 변환하는 작업을 중간에 할 수가 있음.
오늘 살펴볼 목록
- switchToLastest
- flatMap
- subscribe
- receive
- map(\.data)
- flatMap
- scan
- removeDuplicates
switchToLastest
- 요청중인 작업을 취소하고, 현재 구독으로 바꿔버리는 작업을 해줌
- 예를 들어 네트워크 요청을 하고 있을 때, publisher가 다른 내용을 전달 했다면 그 즉시 새로운 publisher를 구독함으로, 기존의 publisher의 구독을 취소하고 새로운 publisher을 구독한다는 것임.
- 즉, 네트워크 통신 중 이였다면 취소하고, 새롭게 요청한 네트워크 요청으로 바꿔버린다는 것임.
let subject = PassthroughSubject<int, never="">()
cancellable = subject
.setFailureType(to: URLError.self)
.map() { index -> URLSession.DataTaskPublisher in
let url = URL(string: "<https://example.org/get?index=\\(index)>")!
return URLSession.shared.dataTaskPublisher(for: url)
}
.switchToLatest()
.sink(receiveCompletion: { print("Complete: \\($0)") },
receiveValue: { (data, response) in
guard let url = response.url else { print("Bad response."); return }
print("URL: \\(url)")
})
for index in 1...5 {
DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(index/10)) {
subject.send(index)
}
}
// Prints "URL: <https://example.org/get?index=5>"
</int,>
subscribe(on: queue)
- .subscribe(on: queue) : publisher를 구독하여 값을 받고, 로직을 동작 시킬 때 어느 quque에서 동작 시킬 건지 정해줄수있음. 가장 최상위에 작성된 .subscribe에 따라 동작함.
let ioPerformingPublisher == // Some publisher.
let uiUpdatingSubscriber == // Some subscriber that updates the UI.
ioPerformingPublisher
.subscribe(on: backgroundQueue)
.receive(on: RunLoop.main)
.subscribe(uiUpdatingSubscriber)
receive(on:queue)
- receive(on:queue): operator, subscriber에서의 행위를 각각 어떤 큐에서 동작 시킬 수 정해줄수 있음.!
let jsonPublisher = MyJSONLoaderPublisher() // Some publisher.
let labelUpdater = MyLabelUpdateSubscriber() // Some subscriber that updates the UI.
jsonPublisher
.subscribe(on: backgroundQueue)
.receive(on: RunLoop.main)
.subscribe(labelUpdater)
pub.sink {
DispatchQueue.main.async {
// Do something.
}
}
// 대신 다음 패턴을 사용하세요.
pub.receive(on: DispatchQueue.main).sink {
// Do something.
}
FlatMap
- FlatMap: 동시성을 제어할 수가 있다. 안에 돌아갈 publisher 프로세스의 갯수를 제한 할 수 있다.
public struct WeatherStation {
public let stationID: String
}
var weatherPublisher = PassthroughSubject<weatherstation, urlerror="">()
cancellable = weatherPublisher.flatMap { station -> URLSession.DataTaskPublisher in
let url = URL(string:"<https://weatherapi.example.com/stations/\\(station.stationID)/observations/latest>")!
return URLSession.shared.dataTaskPublisher(for: url)
}
.sink(
receiveCompletion: { completion in
// Handle publisher completion (normal or error).
},
receiveValue: {
// Process the received data.
}
)
weatherPublisher.send(WeatherStation(stationID: "KSFO")) // San Francisco, CA
weatherPublisher.send(WeatherStation(stationID: "EGLC")) // London, UK
weatherPublisher.send(WeatherStation(stationID: "ZBBB")) // Beijing, CN
</weatherstation,>
Scan
- scan: reduce와 비슷함. publisher를 초기값 + 다음 값 해서 넘겨주는 형식인듯
let range = (0...5)
cancellable = range.publisher
.scan(0) { return $0 + $1 }
.sink { print ("\\($0)", terminator: " ") }
// Prints: "0 1 3 6 10 15 ".
catch
catch: 에러 핸들링
- Empty(): publisher종류 중 하나, 값을 게시하지 않고 선택적으로 즉시 완료되는 Publisher 입니다.
- publisher의 종류(Just, Fail, Empty, Sequence) : https://todayssky.tistory.com/17
struct SimpleError: Error {}
let numbers = [5, 4, 3, 2, 1, 0, 9, 8, 7, 6]
cancellable = numbers.publisher
.tryLast(where: {
guard $0 != 0 else {throw SimpleError()}
return true
})
.catch({ (error) in
Just(-1)
})
.sink { print("\\($0)") }
// Prints: -1
removeDuplicates
- removeDuplicates
- 중복제거가 아니라, 이전과 비교해서 같은 경우 제거한다.
let numbers = [0, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 0]
cancellable = numbers.publisher
.removeDuplicates()
.sink { print("\\($0)", terminator: " ") }
// Prints: "0 1 2 3 4 0"
반응형
'iOS' 카테고리의 다른 글
Combine - Error Handling (0) | 2022.04.19 |
---|---|
Combine - Operator(map, compactMap, tryMap) (0) | 2022.04.19 |
combine - 2. Network 예제 살펴보기 (0) | 2022.04.18 |
combine - 1. Combine에 관하여 (0) | 2022.03.14 |
iOS 동시성 (GCD Grand Central Dispatch) 기본 개념 (0) | 2022.02.07 |