본문 바로가기

UIKIT/비동기

🤔 Completion Handler를 Combine으로 변경할 때 고려해야 할 점?

🤔 Firebase 에서 제공되는 기본 코드는 Completion Handler 기반... 이를 Combine으로 바꾸려면?

 

🎯 Combine 변환 시 고려해야 할 사항

1️⃣ Future는 한 번만 실행되는 Publisher
→ 비동기 작업이 여러 번 실행되면 PassthroughSubject나 CurrentValueSubject가 더 적절할 수도 있음.
2️⃣ 비동기 요청 순서 보장
→ listAll()이 완료되기 전에 delete()를 실행하지 않도록 해야 함.
→ flatMap()과 collect() 또는 DispatchGroup을 사용하여 비동기 흐름을 제어.
3️⃣ UI 업데이트는 receive(on: DispatchQueue.main)을 사용하여 Main Thread에서 실행
→ listAll()과 delete()는 네트워크 요청이므로 백그라운드에서 실행됨.

 

🔹 Completion Handler 기반 함수

👆 이 함수는 listAll()의 데이터를 가져온 후, completion(.success(filePaths))로 반환합니다.

func listAllFiles(completion: @escaping (Result<[String], Error>) -> Void) {
    let storageRef = Storage.storage().reference().child("someFolder")
    
    storageRef.listAll { result in
        switch result {
        case .success(let storageListResult):
            let filePaths = storageListResult.items.map { $0.fullPath }
            completion(.success(filePaths))
        case .failure(let error):
            completion(.failure(error))
        }
    }
}

 

🔹 Combine 기반으로 변환

👆 Future<[String], Error>를 사용하여, Combine의 AnyPublisher<[String], Error> 타입으로 변환합니다.

func listAllFiles() -> AnyPublisher<[String], Error> {
    let storageRef = Storage.storage().reference().child("someFolder")
    
    return Future<[String], Error> { promise in
        storageRef.listAll { result in
            switch result {
            case .success(let storageListResult):
                let filePaths = storageListResult.items.map { $0.fullPath }
                promise(.success(filePaths))
            case .failure(let error):
                promise(.failure(error))
            }
        }
    }
    .eraseToAnyPublisher()
}

'UIKIT > 비동기' 카테고리의 다른 글