728x90
반응형
Scheduler
- on : 스레드 를 통해서 연산 스레드와 결과 수신 스레드를 구분하여 효율을 올릴 수 있습니다
- 아래 코드 역시 map 을 통해 연산하는 스레드는 queue 라는 서브 스레드를 통해 진행하고
receive 를 통해 결과는 메인 스레드에서 처리하는 것을 알 수 있습니다
import Foundation
import Combine
let arrPublisher = [1, 2, 3].publisher
let queue = DispatchQueue(label: "custom")
let subscription = arrPublisher
.subscribe(on: queue)
.map { value -> Int in
print("transform: \(value), thread: \(Thread.current)")
return value
}
.receive(on: DispatchQueue.main)
.sink { value in
print("Received Value : \(value), thread : \(Thread.current)")
}
/*
transform: 1, thread: <NSThread: 0x6000005195c0>{number = 4, name = (null)}
transform: 2, thread: <NSThread: 0x6000005195c0>{number = 4, name = (null)}
transform: 3, thread: <NSThread: 0x6000005195c0>{number = 4, name = (null)}
Received Value : 1, thread : <_NSMainThread: 0x600000510180>{number = 1, name = main}
Received Value : 2, thread : <_NSMainThread: 0x600000510180>{number = 1, name = main}
Received Value : 3, thread : <_NSMainThread: 0x600000510180>{number = 1, name = main}
*/
map
- map에서 작성한 수식을 통해 전달받은 값을 계산합니다
- Subsciption 코드에는 계산 결과 값이 사용됩니다
import Foundation
import Combine
let numPublisher = PassthroughSubject<Int, Never>()
let mapSubscription = numPublisher
.map{ value in
value * 2
}
.sink { value in
print("transformed value : \(value)")
}
numPublisher.send(10)
numPublisher.send(20)
numPublisher.send(30)
mapSubscription.cancel()
/*
transformed value : 20
transformed value : 40
transformed value : 60
*/
filter
- filter에서 작성된 수식 결과가 true인 값만 사용합니다
- 아래 코드와 같이 contains("a") 의 결과가 true인 abc, Jason, Jack 이라는 값만 사용되어 출력됩니다
import Foundation
import Combine
let strPublisher = PassthroughSubject<String, Never>()
let filterSubscription = strPublisher
.filter{ value in
value.contains("a")
}
.sink { value in
print("filtered value : \(value)")
}
strPublisher.send("abc")
strPublisher.send("Jason")
strPublisher.send("Joon")
strPublisher.send("Jenny")
strPublisher.send("Jack")
filterSubscription.cancel()
/*
filtered value : abc
filtered value : Jason
filtered value : Jack
*/
combineLastest
- 2개의 데이터를 모두 받았을 때 처리하는 함수라고 생각하면 됩니다
- 각 구독을 통해 받은 값을 변수에 따로 저장하는 것이 아니라
- 2개의 값을 모두 수신한 경우 (nil 이 아닌 경우) 처리 할 수 있도록 합니다
- 아래 코드에서 처럼 "a" 만 받았을 때는 str 에는 값이 있지만 num 에는 값이 없어 print 가 실행되지 않지만
1 이 들어온 이후에는 str, num 두 곳에 모두 값이 존재하는 상태이기 때문에 print 가 항상 실행됩니다
import Foundation
import Combine
let strPublisher = PassthroughSubject<String, Never>()
let numPublisher = PassthroughSubject<Int, Never>()
/*
strPublisher.combineLatest(numPublisher).sink { (str, num) in
print("received : \(str), \(num)")
}
*/
Publishers.CombineLatest(strPublisher, numPublisher).sink { (str, num) in
print("received : \(str), \(num)")
}
strPublisher.send("a")
numPublisher.send(1)
strPublisher.send("b")
numPublisher.send(2)
strPublisher.send("c")
numPublisher.send(3)
/*
received : a, 1
received : b, 1
received : b, 2
received : c, 2
received : c, 3
*/
- combineLastest 의 응용으로 아이디와 비밀번호에 대한 검증에 대한 예시 코드입니다
- map 을 통해 받은 아이디와 비밀번호에 대한 검증 결과를 연산하여 그 결과를 기반으로 처리합니다
import Foundation
import Combine
let usernamePublisher = PassthroughSubject<String, Never>()
let passwordPublisher = PassthroughSubject<String, Never>()
let validatedCrendetialsSubscription = usernamePublisher.combineLatest(passwordPublisher)
.map { (username, password) in
return !username.isEmpty && !password.isEmpty && password.count > 12
}
.sink { valid in
print(valid ? "success" : "failure")
}
usernamePublisher.send("leehees")
passwordPublisher.send("weakPassword") // failure
passwordPublisher.send("veryStrongPassword") // success
/*
failure
success
*/
merge
- 두 퍼블리셔의 타입이 같은 경우 (반드시 같아야 합니다)
- 병합하여 한 번에 받을 수 있다
import Foundation
import Combine
let publisher1 = [1, 2, 3, 4, 5].publisher
let publisher2 = [100, 200, 300].publisher
// combineLastest 와 달리
// 두 퍼블리셔의 타입은 같아야 함
/*
let mergePublisherSubscription = publisher1.merge(with: publisher2)
.sink { value in
print("Merge : received value = \(value)")
}
*/
Publishers.Merge(publisher1, publisher2).sink { value in
print("Merge : received value = \(value)")
}
/*
Merge : received value = 1
Merge : received value = 2
Merge : received value = 3
Merge : received value = 4
Merge : received value = 5
Merge : received value = 100
Merge : received value = 200
Merge : received value = 300
*/
removeDuplicates
- Publisher로 전달받는 값에 대해 중복제거합니다
import Foundation
import Combine
var subscriptions = Set<AnyCancellable>()
let words = "hey hey there! Mr Mr ?"
.components(separatedBy: " ")
.publisher
words
.removeDuplicates() // 퍼블리셔 중복 제거
.sink { completion in
print("Completed with: \(completion)")
} receiveValue: { value in
print(value)
}
.store(in: &subscriptions)
/*
hey
there!
Mr
?
Completed with: finished
*/
compactMap
- 1차원 배열에서 nil 값을 제외 해줍니다
- 값을 그대로 출력하여 원래 nil 이 아닌것만 추출 가능하고
Float(value) 등으로 연산 결과가 nil 이 아닌 것만 추출하는 것도 가능합니다
import Foundation
import Combine
var subscriptions = Set<AnyCancellable>()
let strings = ["a", "1.24", "3", "def", "45", "0.23"].publisher
strings
.compactMap { value in
Float(value)
} // nil 값 제외 출력
.sink { completion in
print("Completed with: \(completion)")
} receiveValue: { value in
print(value)
}
.store(in: &subscriptions)
/*
1.24
3.0
45.0
0.23
Completed with: finished
*/
ignoreOutput
- output을 무시하고 completion만 받도록 합니다
import Foundation
import Combine
var subscriptions = Set<AnyCancellable>()
let numbers = (1...10_000).publisher
numbers
.ignoreOutput() // 데이터 출력은 무시 (성공/실패 유무만 출력)
.sink { completion in
print("Completed with: \(completion)")
} receiveValue: { value in
print(value)
}
.store(in: &subscriptions)
/*
Completed with: finished
*/
prefix
- Publisher의 값 전달 개수를 제한합니다
import Foundation
import Combine
var subscriptions = Set<AnyCancellable>()
let tens = (1...10).publisher
tens
.prefix(2) // 퍼블리셔 전달 데이터 개수 설정 (2로 설정한 경우 데이터가 더 있어도 2개만 보내고 끝냄)
.sink { completion in
print("Completed with: \(completion)")
} receiveValue: { value in
print(value)
}
.store(in: &subscriptions)
/*
1
2
Completed with: finished
*/
728x90
반응형
'Swift' 카테고리의 다른 글
[ Swift ] Network - 개념 (0) | 2023.03.15 |
---|---|
[ Swift ] Combine - 실습 (0) | 2023.03.13 |
[ Swift ] Combine - Subscriber (0) | 2023.03.06 |
[ Swift ] Combine - Publisher (0) | 2023.03.03 |
[ Swift ] Combine - 개념 (0) | 2023.03.01 |