IAM iOS

[RxSwift] Building News App Using Transforming Operators 본문

RxSwift

[RxSwift] Building News App Using Transforming Operators

IAMiOS 2022. 4. 3. 20:03

 

What we will be Building?


변환 연산자(Transforming Operators)를 사용하여, News API 네트워크 요청 구현

 

 

API 호출


  • Observable이 url 값을 방출 (Just, From 상관없음)
  • Observable이 방출하는 url을 새로운 Observable로 변환
  • 변환된 결과값을 Mapping하여 디코딩 (요청한 data를 가져와서 Article을 반환)

최종적으로 하나의 Observable로 합쳐지고, 모든 항목이 Observable을 통해 방출

flatMap을 사용하여 url을 얻고, 여기서 반환할 것은 Observable<Data>

 

let disposeBag = DisposeBag()
private var articles = [Article]()
private func populateNews() {
    let url = URL(string: "<https://newsapi.org/v2/top-headlines?country=us&apiKey=>...")!
    
    Observable.just(url)
        .flatMap { url -> Observable in
            let request = URLRequest(url: url)
            return URLSession.shared.rx.data(request: request)
        
        }.map { data -> [Article]? in
            return try? JSONDecoder().decode(ArticlesList.self, from: data).articles
            
        }.subscribe(onNext: { [weak self] articles in
                
            if let articles = articles {
                self?.articles = articles
                    
                DispatchQueue.main.async {
                    self?.tableView.reloadData()
                }
            }
        }).disposed(by: disposeBag)
}

 

 

Refactoring


  • Generic 타입을 통해 특정 리소스를 사용하고, Observable로 반환

URLRequest+Extension

// 입력할 유형을 디코딩
struct Resource<T: Decodable> {
    let url: URL
}

extension URLRequest {
    // Generic 타입을 통해 특정 리소스를 사용하고, Observable로 반환
    static func load<T>(resource: Resource<T>) -> Observable<T?> {
        
        return Observable.from([resource.url])
            .flatMap { url -> Observable<Data> in
                let request = URLRequest(url: url)
                return URLSession.shared.rx.data(request: request)
                
            }.map { data -> T? in
                // decoding된 데이터 반환
                return try? JSONDecoder().decode(T.self, from: data)
            }.asObservable()  
    }
}

 

  • Observable로 반환할 리소스 생성

UITableViewController

private func populateNews() {
    let url = URL(string: "<https://newsapi.org/v2/top-headlines?country=us&apiKey=>...")!
    let resource = Resource(url: url)

    URLRequest.load(resource: resource)
        .subscribe(onNext: { [weak self] result in
            if let result = result {
                self?.articles = result.articles
                
                DispatchQueue.main.async {
                    self?.tableView.reloadData()
                }
            }
        }).disposed(by: disposeBag)
}

 

 

코드 보러 가기

 

GitHub - camosss/RxSwift: RxSwift 공부한 내용 정리

RxSwift 공부한 내용 정리. Contribute to camosss/RxSwift development by creating an account on GitHub.

github.com