-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Combine 프레임워크에서 에러 처리는 어떻게 하나요? #24
Comments
Combine 프레임워크에서 에러 처리는 어떻게 하나요?에러를 처리하는 Publisher와 Operator들을 알아보겠습니다. Handling Errors에 분류된 Publisher들은 아래와 같습니다.
import SwiftUI
import Combine
struct ContentView: View {
@State private var data: String?
private var cancellables = Set<AnyCancellable>()
var body: some View {
VStack {
if let data = data {
Text("Data: \(data)")
} else {
ProgressView()
}
}
.onAppear {
fetchData()
.assertNoFailure() // Publisher가 실패하지 않음을 보장
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("데이터 패치 완료")
}
}, receiveValue: { receivedData in
self.data = receivedData
})
.store(in: &self.cancellables)
}
}
private func fetchData() -> AnyPublisher<String, Error> {
// 비동기로 데이터 패치
return Just("데이터 패치 성공")
.delay(for: .seconds(2), scheduler: DispatchQueue.main)
.setFailureType(to: Error.self) // 오류 유형을 Error로 설정
.eraseToAnyPublisher()
}
}
import SwiftUI
import Combine
struct ContentView: View {
@State private var data: String?
private var cancellables = Set<AnyCancellable>()
var body: some View {
VStack {
if let data = data {
Text("Data: \(data)")
} else {
ProgressView()
}
}
.onAppear {
fetchData()
.catch { error in
Just("데이터 패치 실패") // 대체 값을 반환
}
.sink(receiveValue: { receivedData in
self.data = receivedData
})
.store(in: &self.cancellables)
}
}
private func fetchData() -> AnyPublisher<String, Error> {
// 실패하는 비동기 데이터 가져오기 시뮬레이션
return Future<String, Error> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
promise(.failure(MyError.dataFetchingError)) // 오류 반환
}
}
.eraseToAnyPublisher()
}
}
enum MyError: Error {
case dataFetchingError
}
import SwiftUI
import Combine
struct ContentView: View {
@State private var data: String?
private var cancellables = Set<AnyCancellable>()
var body: some View {
VStack {
if let data = data {
Text("Data: \(data)")
} else {
ProgressView()
}
}
.onAppear {
fetchData()
.tryCatch { error -> AnyPublisher<String, Error> in
// 오류가 발생한 경우 대체 값을 반환
return Just("데이터 패치 실패").setFailureType(to: Error.self).eraseToAnyPublisher()
}
.sink(receiveValue: { receivedData in
self.data = receivedData
})
.store(in: &self.cancellables)
}
}
private func fetchData() -> AnyPublisher<String, Error> {
// 실패하는 비동기 데이터 가져오기 시뮬레이션
return Future<String, Error> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
promise(.failure(MyError.dataFetchingError)) // 오류 반환
}
}
.eraseToAnyPublisher()
}
}
enum MyError: Error {
case dataFetchingError
}
import SwiftUI
import Combine
struct ContentView: View {
@State private var data: String?
private var cancellables = Set<AnyCancellable>()
var body: some View {
VStack {
if let data = data {
Text("Data: \(data)")
} else {
ProgressView()
}
}
.onAppear {
fetchData()
.retry(3) // 최대 3번 재시도
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("데이터 패치 완료")
case .failure(let error):
print("데이터 패치 실패: \(error.localizedDescription)")
}
}, receiveValue: { receivedData in
self.data = receivedData
})
.store(in: &self.cancellables)
}
}
private func fetchData() -> AnyPublisher<String, Error> {
// 실패하는 비동기 데이터 가져오기 시뮬레이션
return Future<String, Error> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
if Bool.random() {
promise(.success("데이터 패치 성공"))
} else {
promise(.failure(MyError.dataFetchingError)) // 오류 반환
}
}
}
.eraseToAnyPublisher()
}
}
enum MyError: Error {
case dataFetchingError
}
에러 이벤트를 처리하기 위한 Operator에는 어떤 것들이 있나요?
import Combine
let publisher = Just("Hello, World!")
publisher
.assertNoFailure("Publisher 실패", file: "Example.swift", line: 20) // 실패를 확인하는 메시지 및 파일, 라인 지정
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher 처리 완료")
case .failure(let error):
print("Publisher 실패: \(error.localizedDescription)")
}
}, receiveValue: { value in
print("Received value: \(value)")
})
import Combine
let publisher = PassthroughSubject<String, Error>()
publisher
.catch { error in
// 오류가 발생한 경우 대체 값을 발행
return Just("데이터 발행 실패").setFailureType(to: Error.self)
}
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher 처리 완료")
case .failure(let error):
print("Publisher 실패: \(error.localizedDescription)")
}
}, receiveValue: { receivedData in
print("Received value: \(receivedData)")
})
// Publisher가 오류를 내보냄
publisher.send(completion: .failure(MyError.publishingError))
enum MyError: Error {
case publishingError
}
import Combine
func fetchData() throws -> Future<String, Error> {
return Future<String, Error> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
if Bool.random() {
promise(.success("데이터 패치 성공"))
} else {
promise(.failure(MyError.dataFetchingError)) // 오류 반환
}
}
}
}
let publisher = tryCatch(fetchData)
publisher
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher 처리 완료")
case .failure(let error):
print("Publisher 실패: \(error.localizedDescription)")
}
}, receiveValue: { receivedData in
print("Received value: \(receivedData)")
})
enum MyError: Error {
case dataFetchingError
}
import Combine
let publisher = PassthroughSubject<String, Error>()
publisher
.retry(3) // 최대 3번 재시도
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher 처리 완료")
case .failure(let error):
print("Publisher 실패: \(error.localizedDescription)")
}
}, receiveValue: { receivedData in
print("Received value: \(receivedData)")
})
// 실패하고 재시도되는 Publisher
publisher.send(completion: .failure(MyError.publishingError))
publisher.send(completion: .failure(MyError.publishingError))
publisher.send("데이터 보냄")
enum MyError: Error {
case publishingError
}
에러 이벤트 발생 시 Subscription을 자동으로 취소하는 방법은 무엇인가요?
import Combine
let publisher = Just("Hello, World!")
let cancellable = publisher
.sink(
receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher 처리 완료")
case .failure(let error):
print("Publisher 실패: \(error.localizedDescription)")
}
},
receiveValue: { value in
print("Received value: \(value)")
}
) {
print("Subscription 취소")
}
.store(in: &cancellables, cancelOnFailure: true) // 에러 발생 시 Subscription 취소
// 실패하는 Publisher
publisher.send(completion: .failure(MyError.exampleError))
enum MyError: Error {
case exampleError
}
Combine과 Result 타입을 함께 사용하여 에러 처리를 하는 방법을 설명해주세요.
import Combine
func fetchData() -> AnyPublisher<Result<String, Error>, Never> {
return URLSession.shared.dataTaskPublisher(for: URL(string: "https://api.example.com/data")!)
.map { data, _ in
// 네트워크 요청 성공
return .success(String(data: data, encoding: .utf8)!)
}
.mapError { error in
// 네트워크 요청 실패
return error
}
.eraseToAnyPublisher()
}
이 Publisher를 구독하여 결과를 처리하는 코드를 작성해보겠습니다. var cancellables = Set<AnyCancellable>()
fetchData()
.sink { result in
switch result {
case .success(let data):
print("데이터 패치 성공: \(data)")
case .failure(let error):
print("데이터 패치 실패: \(error.localizedDescription)")
}
}
.store(in: &cancellables)
|
첫 |
|
오 맞아요. 정확히, 위의 예시에서 사용된 위 코드에서, 위 코드에선 다른 예시 코드들과 같은 코드를 사용하면서 import Combine
let publisher = Just("Hello, World!")
publisher
.assertNoFailure("Publisher 실패", file: "Example.swift", line: 20)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Publisher 처리 완료")
}
}, receiveValue: { value in
print("Received value: \(value)")
}) |
간단하게 설명하면 Publisher를 구독하는 과정이에요. Publisher를 구독하면 Subscriber가 Publisher로부터 이벤트를 수신하는데, 여기서의 Subscriber와 Publisher 사이의 연결을 나타내는게 Subscription이에요! 그러니 Subscription을 자동으로 취소한다면 구독을 취소해서 이벤트 전달을 더 이상 받지 않는다는 것이니, 메모리 누수나 불필요한 작업을 방지할 수 있습니다. ㅎ |
The text was updated successfully, but these errors were encountered: