본문으로 바로가기

[iOS] Combine

category iOS 2022. 7. 23. 10:37
728x90

Combine이란?

효율적인 비동기 처리를 위한 방식

Combine 구조

0. 주요 Component

1. Publisher

  • Output
  • Failure

2. Operator

3. Subscriber

  • Input
  • Failure

Combine 처리 과정

1. Publisher

  • PassthroughSubject
    • Subscriber 요청시 데이터를 전달한다. 
    • 전달 데이터를 보관하지 않는다.
// 예시
import Foundation
import Combine

let relay = PassthroughSubject<String, Never>()
let subscription = relay.sink { value in
    print("\(value)")
}

relay.send("Hello")
relay.send("World")
relay.send(completion: .finished)	// 송신 중단. subscription.cancel()
  • CurrentValueSubject
    • Subscriber 요청시 현재 가지고 있는 데이터를 전달한다.
    • 전달 데이터를 보관한다.
// 예시
import Foundation
import Combine

let relay = CurrentValueSubject<String, Never>("")

relay.send("Hello")

let subscription = relay.sink { value in
    print("\(value)")
}

relay.send("World")
// URL
struct SomeDecodable: Decodable { }
URLSession.shared.dataTaskPublisher(for: URL(string: /*"https://..."*/)!)
    .map { data, response in
        return data
    }
    .decode(type: SomeDecodable.self, decoder: JSONDecoder())
// Timer
let timerPublisher = Timer.publish(every: 1, on: .main, in: .common).autuconnect()
let subscription = timerPublisher.sink { time in
    print("time: \(time)")
}

// Stop the timer after 5 sec
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
	subscription.cancle()
}

2. Operator

subscribe함수를 이용해서 publisher가 어느 스레드에서 수행할지 결정한다. (Background thread)

receive 함수를 이용해서 operator, subscriber가 어느 스레드에서 수행할지 결정한다. (Main thread)

removeDuplicates, compactMap, map, ignoreOutput, prefix 함수 등이 있다.

let arrPublisher = [1, 2, 3].publisher
let queue = DispatchQueue(label: "custom")
let subscription = arrPublisher
    .subscribe(on: queue)
    .map { value -> Int in
        print("\(value), \(Thread.current)")
        return value
    }
    .receive(on: DispatchQueue.main)
    .sink { value in 
        print("\(value), \(Thread.current)")
    }

3. Subscriber

assign 함수는 Publisher가 제공한 데이터를 특정 객체의 키패스에 할당한다.

sink 함수는 Publisher가 제공한 데이터를 받을 수 있는 클로져를 제공한다.

// 예시
let subscription = relay.sink { value in
    print("\(value)")
}

let publisher = ["Hello", "world", "combine"].publisher
publisher.subscribe(relay)
let instance1 = Class1()	// @Published var variable
let instance2 = Class2()
instance1.$variable.assign(to: \.value, on: instance2)

 

728x90