2016년 10월 11일 화요일

AlamofireImage 소스 분석

https://github.com/Alamofire/AlamofireImage

UIImaveView의 extension.

  • 지정한 이미지를 보여주기 위한 extension
  • enum ImageTransition
    • UIView의 transition animation에 사용되는 값을 저장하고 있는다.
    • duration, animationOptions, animations, completion(기본은 nil)
    • completion을 사용하고 싶으면 custom을 사용해야 한다.
  • af_imageDownloader와 af_sharedImageDownloader
    • 이미지 다운로드시 사용하는 instance.
    • 보통은 ImageDownloader.default를 사용하는 af_sharedImageDownloader를 사용하면 되나, 별도의 ImageDownloader가 필요(different auth credential)한 경우에는 af_imageDownloader를 설정하여 이것이 사용되도록 한다.
    • 내부에서 값의 저장은 objc_getAssociatedObject와 objc_setAssociatedObject를 사용해서 key/value의 형태로 저장하고 있는다.
  • af_activeRequestReceipt
    • 현재 진행중인 request에 대한 정보를 가지고 있다. download 요청이 끝나면 nil로 설정된다.
    • request의 취소에 사용한다.
  • af_setImage
    • 이미지 로딩을 요청하는 함수. 1. 이전에 진행중인 이미지 요청이 있으면 취소한다. 1. 캐시가 있으면 캐시에 있는 것을 가져온다. 1. placeholder를 지정해 주었으면 이미지 다운로드가 완료될 때까지 이것을 이미지로 설정한다. 1. ImageDownloader를 통해 이미지를 다운로드 한다.
      • 각각의 request에 unique id를 할당하여 최신인지 아닌지를 파악한다.

ImageDownloader

  • 기본 캐시로 메모리는 20MB, 디스크는 150MB, 디스크 경로로는 "org.alamofire.imagedownloader"를 사용한다. - URLCache에 지정한다.
  • enum DownloadPrioritization을 통해 다운로드 우선순위를 지정한다: FIFO, LIFO
  • 동시에 다운로드 할 수 있는 수를 제한한다. 기본은 4 - maximumActiveDownloads
    • 제한 값이 넘어가면 queuedRequests에 request를 넣어두었다가 기존 request에의 응답이 오면 이 queue에서 request를 꺼내서 실행한다.
  • synchronizationQueue와 responseQueue로 작업을 진행한다.
    • request와 관련된 작업의 경우 쓰레드 문제가 발생하지 않도록 하기 위해 synchronizationQueue를 사용한다.
    • request에 대한 응답은 responseQueue에서 동작하도록 한다.
  • download
    1. 이미 진행중인 request이면 filter와 completion handler를 response handler에 추가한다.
    2. 캐시된 이미지가 있으면 이를 로드한다.
    3. credential이 지정되어 있으면 request에 넣어주고 이미지를 요청한다.
    4. image 응답시 imageResponseSerializer를 사용한다.
    5. 서버로부터 응답시 캐시에 이미지를 넣는다.

DataRequest에 extension을 구현한다.

  • 지원하는 이미지 타입은 acceptableImageContentTypes에 지정해 놓는다.
  • imageResponseSerializer
    • 다운로드한 data를 UIImage에 넣어서 image를 생성한다.
    • 지원하지 않는 이미지 타입인 경우 에러를 리턴한다.

AutoPurgingImageCache

  • in-memory image cache
  • 내부에 저장하는 이미지의 key로 request와 unique filter identifier를 사용한다.
  • 기본 memoryCapacity는 100MB로 설정하고 preferredMemoryUsageAfterPurge는 60MB로 설정한다.
  • 이미지는 CachedImage의 형태로 저장된다. - 내부에 마지막으로 접근한 시간을 기록하고 있는다.
  • 이미지를 추가할 때마다 currentMemoryUsage에 이미지 크기를 추가한다.
  • currentMemoryUsage가 memoryCapacity보다 커지면 내부의 이미지를 마지막으로 접근한 시간 기준으로 정렬한 다음 오래된 이미지를 제거한다. 이미지 제거시 currentMemoryUsage가 preferredMemoryUsageAfterPurge보다 작아지면 이미지 제거를 중단한다.

ImageFilter

  • 이미지 변경을 위한 필터들을 제공한다.
  • UIImage extension에서 제공하는 이미지 변경 함수들에 대한 필터 기능이라고 보면 된다.
  • protocol ImageFilter

UIImage extension

  • thread safe하게 UIImage를 초기화하기 위한 함수를 제공한다.
    • af_threadSafeImage
    • UIImage()의 앞뒤로 NSLock()의 lock/unlock를 사용한다.
  • UIImage에 stored property를 저장하기 위해 AssociatedObject를 사용한다.
    • struct AssociatedKey, objc_getAssociatedObject, objc_setAssociatedObject
  • inflation하기
    • cgImage?.dataProvider?.data
    • inflation을 여러번 반복하지 않기 위해 한번 inflation을 하고 나면 af_inflated를 AssociatedObject를 사용해서 true로 설정한다.
  • alpha정보 확인하기
    • cgImage?.alphaInfo
  • 아래의 함수들은 모두 새로운 UIImage를 리턴한다.
  • af_imageScaled
    • 지정한 크기로 이미지 스케일링한다.
    • UIGraphicsBeginImageContextWithOptions -> draw -> UIGraphicsGetImageFromCurrentImageContext -> UIGraphicsEndImageContext
  • af_imageAspectScaled
    • 비율을 유지하면서 스케일링한다.
    • fit(큰쪽 기준)과 fill(작은쪽 기준) 두가지로 구분되어 있다.
  • af_imageRounded
    • 이미지를 모서리가 둥글게 처리한다.
    • UIBezierPath를 사용해서 이미지 clipping을 하여 그 영역 안에 draw를 하도록 한다.
  • af_imageRoundedIntoCircle
    • 이미지를 원형으로 변경한다.
    • 이미지가 1:1이 아니면 먼저 af_imageAspectScaled(toFill)를 사용해서 1:1로 변경한다.
  • af_imageFiltered
    • CIFilter를 사용하여 이미지를 변경한다.

XCTest

  • Unit test
  • BaseTestCase
    • setUp and tearDown
  • expectation으로 새 기대값을 만들고, 테스트 하고자 하는 결과가 완료되면 fulfill을 불러준다.
  • waitForExpectations에서 fulfill이 되거나 timeout이 될 때까지 기다린다.
  • 원하는 결과값들은 테스트한다.

댓글 없음:

댓글 쓰기

Building asynchronous views in SwiftUI 정리

Handling loading states within SwiftUI views self loading views View model 사용하기 Combine을 사용한 AnyPublisher Making SwiftUI views refreshable r...