관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - Swift] RxSwift의 map으로 디코딩하는 방법 (선언형 프로그래밍) 본문

iOS 응용 (swift)

[iOS - Swift] RxSwift의 map으로 디코딩하는 방법 (선언형 프로그래밍)

jake-kim 2022. 12. 24. 22:00

일반적인 디코딩 방법

  • User라는 Codable 모델 준비
struct User: Codable {
    let id: String
    let name: String
}
  • JSONDecoder()를 사용하여 data형태로 변경
func getUserData() -> Observable<Data> {
    let user = User(id: "1", name: "jake")
    let encoder = JSONEncoder()
    guard let data = try? encoder.encode(user) else { return .empty() }
    return .just(data)
}
  • 디코딩 사용
    • JSONDecoder()를 사용하여 data를 디코딩하여 user모델로 변경
getUserData()
    .subscribe(onNext: { data in
        let decoder = JSONDecoder()
        guard let user = try? decoder.decode(User.self, from: data) else { return }
        print(user) // User(id: "1", name: "jake")
    })
    .disposed(by: disposeBag)
  • moya에서 제공하는 방법처럼 map으로 아래처럼 간결하게 선언적으로 디코딩하는 방법?

* 선언형 프로그래밍: 무엇을 숨기고, 어떻게에 대해서만 표출 (추상화) 

getUserData()
    .map(User.self)
    .subscribe()
    .disposed(by: disposeBag)
  • Observable를 extension하여 map 함수 정의
    • Element는 Data로 제약
extension Observable where Element == Data {
}
  • map 함수의 파라미터는 변경하려는 타입을 받고, 리턴값으로는 아래 스트림에 그대로 던져주어야 하므로 Observable를 리턴
    func map<T: Decodable>(_ type: T.Type) -> Observable<T> {
    }
  • Observable.create 메소드를 선언하여 JSONDecoder()로 사용
extension Observable where Element == Data {
    func map<T: Decodable>(_ type: T.Type) -> Observable<T> {
        flatMap { element -> Observable<T> in
            .create { observer in
                let decoder = JSONDecoder()
                do {
                    let model = try decoder.decode(T.self, from: element)
                    observer.onNext(model)
                } catch {
                    observer.onError(NSError())
                }
                return Disposables.create()
            }
        }
    }
}

 

* 전체 코드: https://github.com/JK0369/ExMapOperator

Comments