iOS) Alamofire 와 Moya 에서 Image 받기

1 minute read

Almofire

Downloading data to a file

data 를 메모리로 가져오는 것 외에도 Alamofire 는 disk 로의 다운로딩을 위해서 Session.download, DownloadRequest, DownloadResponse<Success, Failure: Error> API 를 제공한다.

AF.download("https://httpbin.org/image/png").responseURL { response in
    // Read file from provided URL.
}

responseURL 은 다른 응답 핸들러들과 달리 다운로드 된 데이터의 위치가 포함 된 URL 만 반환하고 disk 에서 Data 를 읽지 않는다.

responseDecodable 과 같은 other response hanlders 는 disk 에서 Data 읽기가 가능하다. 이 경우 큰 데이터를 메모리로 읽는 것이 포함 될 수 있으므로 이런 핸들러를 사용할 때 염두해두어야 한다.

Download File Destination

다운로드 된 모든 데이터는 system temporary directory 에 저장된다. 결국 언젠가는 삭제가 되므로 더 오래 유지해야할 경우 다른 곳으로 이동시켜야 한다.

final destination 으로 옮기기 위해서 Destinaion closure 를 제공할 수 있다. destinationURL 로 이동하기 전에 closure 에 지정된 옵션이 실행된다. 두가지 옵션:

  • .createIntermediateDirectories - 지정된 경우 destination URL 에 대한 intermediate directories 를 만든다.
  • .removePreviousFile - 지정된 경우 destionation URL 의 이전 파일을 삭제한다.
let destination: DownloadRequest.Destination = { _, _ in
    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let fileURL = documentsURL.appendingPathComponent("image.png")

    return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}

AF.download("https://httpbin.org/image/png", to: destination).response { response in
    debugPrint(response)

    if response.error == nil, let imagePath = response.fileURL?.path {
        let image = UIImage(contentsOfFile: imagePath)
    }
}

제시된 download destination API 를 사용할 수 있다.

let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)

AF.download("https://httpbin.org/image/png", to: destination)

자, 이제 그럼 Moya 에서는 어떻게 download data 하는지 알아보자.

Moya

Reactive Extensions

RxSwift 와 ReactiveSwift 에 대한 extensions 를 제공한다.

ReactiveSwift

사용자가 start, bind, map 등 수행할 수 있는 SignalProducer 를 즉시 반환하는 reactive.request(:callbackQueue:),reactive.requestWithProgress(:callbackQueue:) 메서드를 제공한다.

provider = MoyaProvider<GitHub>()
provider.reactive.request(.userProfile("ashfurrow")).start { event in
    switch event {
    case let .value(response):
        image = UIImage(data: response.data)
    case let .failed(error):
        print(error)
    default:
        break
    }
}

RxSwift

rx.request(:callbackQueue:)rx.requestWithProgress(:callbackQueue:) 메서드를 제공하지만 리턴 타입이 둘다 다르다.

  • rx.request(:callbackQueue:) : Single<Response>
  • rx.requestWithProgress(:callbackQueue:) : Observable<ProgressResponse> 이유는 progress 과정에서 여러개의 이벤트와 response 에서 한개의 이벤트를 받기 때문.
provider = MoyaProvider<GitHub>()
provider.rx.request(.userProfile("ashfurrow")).subscribe { event in
    switch event {
    case let .success(response):
        image = UIImage(data: response.data)
    case let .error(error)d
        print(error)
    }
}

callback blocks 대신에 signals 사용하는 옵션 외에도 RxSwift, ReactiveSwift 에 대한 signal operators 가 존재한다. 네트워크에서 받은 응답의 데이터를 image, JSON, string 에 매핑을 하는 mapImage(), mapJSON(), mapString(). 매핑을 실패하면 error 발생. invalid responses 를 핸들링하는 코드에서 400가 같은 API 오류를 처리하는 코드도 동일하게 배치 가능.


Moya/Moya

Categories:

Updated: