Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - Custom Image Downloader for UIImageView #31

Merged
merged 1 commit into from
Oct 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions Source/UIImageView+AlamofireImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,29 @@ extension UIImageView {
// MARK: - Private - AssociatedKeys

private struct AssociatedKeys {
static var ImageDownloaderKey = "af_UIImageView.ImageDownloader"
static var SharedImageDownloaderKey = "af_UIImageView.SharedImageDownloader"
static var ActiveRequestReceiptKey = "af_UIImageView.ActiveRequestReceipt"
}

// MARK: - Properties

/// The image downloader used to download all images. By default, this is the default `ImageDownloader` instance
/// backed with an `AutoPurgingImageCache` which automatically evicts images from the cache when the memory capacity
/// is reached or memory warning notifications occur.
/// The instance image downloader used to download all images. If this property is `nil`, the `UIImageView` will
/// fallback on the `af_sharedImageDownloader` for all downloads. The most common use case for needing to use a
/// custom instance image downloader is when images are behind different basic auth credentials.
public var af_imageDownloader: ImageDownloader? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.ImageDownloaderKey) as? ImageDownloader
}
set(downloader) {
objc_setAssociatedObject(self, &AssociatedKeys.ImageDownloaderKey, downloader, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}

/// The shared image downloader used to download all images. By default, this is the default `ImageDownloader`
/// instance backed with an `AutoPurgingImageCache` which automatically evicts images from the cache when the memory
/// capacity is reached or memory warning notifications occur. The shared image downloader is only used if the
/// `af_imageDownloader` is `nil`.
public class var af_sharedImageDownloader: ImageDownloader {
get {
if let downloader = objc_getAssociatedObject(self, &AssociatedKeys.SharedImageDownloaderKey) as? ImageDownloader {
Expand Down Expand Up @@ -296,7 +310,7 @@ extension UIImageView {

af_cancelImageRequest()

let imageDownloader = UIImageView.af_sharedImageDownloader
let imageDownloader = af_imageDownloader ?? UIImageView.af_sharedImageDownloader
let imageCache = imageDownloader.imageCache

// Use the image from the image cache if it exists
Expand All @@ -320,7 +334,7 @@ extension UIImageView {
}

// Download the image, then run the image transition or completion handler
let requestReceipt = UIImageView.af_sharedImageDownloader.downloadImage(
let requestReceipt = imageDownloader.downloadImage(
URLRequest: URLRequest,
filter: filter,
completion: { [weak self] response in
Expand Down Expand Up @@ -356,7 +370,9 @@ extension UIImageView {
*/
public func af_cancelImageRequest() {
guard let activeRequestReceipt = af_activeRequestReceipt else { return }
UIImageView.af_sharedImageDownloader.cancelRequestForRequestReceipt(activeRequestReceipt)

let imageDownloader = af_imageDownloader ?? UIImageView.af_sharedImageDownloader
imageDownloader.cancelRequestForRequestReceipt(activeRequestReceipt)

af_activeRequestReceipt = nil
}
Expand Down
27 changes: 27 additions & 0 deletions Tests/UIImageViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,36 @@ class UIImageViewTestCase: BaseTestCase {
imageView.af_setImageWithURL(URL)
waitForExpectationsWithTimeout(timeout, handler: nil)

// Then
XCTAssertTrue(imageDownloadComplete, "image download complete should be true")
}

// MARK: - Image Downloaders

func testThatInstanceImageDownloaderOverridesSharedImageDownloader() {
// Given
let expectation = expectationWithDescription("image should download successfully")
var imageDownloadComplete = false

let imageView = TestImageView {
imageDownloadComplete = true
expectation.fulfill()
}

let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
let imageDownloader = ImageDownloader(configuration: configuration)
imageView.af_imageDownloader = imageDownloader

// When
imageView.af_setImageWithURL(URL)
let activeRequestCount = imageDownloader.activeRequestCount

waitForExpectationsWithTimeout(timeout, handler: nil)

// Then
XCTAssertTrue(imageDownloadComplete, "image download complete should be true")
XCTAssertNil(imageView.af_activeRequestReceipt, "active request receipt should be nil after download completes")
XCTAssertEqual(activeRequestCount, 1, "active request count should be 1")
}

// MARK: - Image Cache
Expand Down