|
@@ -33,45 +33,21 @@ import UIKit
|
|
|
|
|
|
|
|
extension KingfisherClass where Base: ImageView {
|
|
extension KingfisherClass where Base: ImageView {
|
|
|
|
|
|
|
|
- /// Sets an image to the image view with a requested resource.
|
|
|
|
|
- ///
|
|
|
|
|
- /// - Parameters:
|
|
|
|
|
- /// - resource: The `Resource` object contains information about the resource.
|
|
|
|
|
- /// - placeholder: A placeholder to show while retrieving the image from the given `resource`.
|
|
|
|
|
- /// - options: An options set to define image setting behaviors. See `KingfisherOptionsInfo` for more.
|
|
|
|
|
- /// - progressBlock: Called when the image downloading progress gets updated. If the response does not contain an
|
|
|
|
|
- /// `expectedContentLength`, this block will not be called.
|
|
|
|
|
- /// - completionHandler: Called when the image retrieved and set finished.
|
|
|
|
|
- /// - Returns: A task represents the image downloading.
|
|
|
|
|
- ///
|
|
|
|
|
- /// - Note:
|
|
|
|
|
- /// This is the easist way to use Kingfisher to boost the image setting process from network. Since all parameters
|
|
|
|
|
- /// have a default value except the `resource`, you can set an image from a certain URL to an image view like this:
|
|
|
|
|
- ///
|
|
|
|
|
- /// ```
|
|
|
|
|
- /// let url = URL(string: "https://example.com/image.png")!
|
|
|
|
|
- /// imageView.kf.setImage(with: URL(string: url))
|
|
|
|
|
- /// ```
|
|
|
|
|
- ///
|
|
|
|
|
- /// Internally, this method will use `KingfisherManager` to get the requested resource, from either cache
|
|
|
|
|
- /// or network. Since this method will perform UI changes, you must call it from the main thread.
|
|
|
|
|
- /// Both `progressBlock` and `completionHandler` will be also executed in the main thread.
|
|
|
|
|
- ///
|
|
|
|
|
@discardableResult
|
|
@discardableResult
|
|
|
- public func setImage(with resource: Resource?,
|
|
|
|
|
|
|
+ public func setImage(with source: Source?,
|
|
|
placeholder: Placeholder? = nil,
|
|
placeholder: Placeholder? = nil,
|
|
|
options: KingfisherOptionsInfo? = nil,
|
|
options: KingfisherOptionsInfo? = nil,
|
|
|
progressBlock: DownloadProgressBlock? = nil,
|
|
progressBlock: DownloadProgressBlock? = nil,
|
|
|
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil)
|
|
completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil)
|
|
|
-> DownloadTask?
|
|
-> DownloadTask?
|
|
|
{
|
|
{
|
|
|
- guard let resource = resource else {
|
|
|
|
|
|
|
+ guard let source = source else {
|
|
|
self.placeholder = placeholder
|
|
self.placeholder = placeholder
|
|
|
- webURL = nil
|
|
|
|
|
|
|
+ taskIdentifier = nil
|
|
|
completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptyResource)))
|
|
completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptyResource)))
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
var options = KingfisherManager.shared.defaultOptions + (options ?? .empty)
|
|
var options = KingfisherManager.shared.defaultOptions + (options ?? .empty)
|
|
|
let noImageOrPlaceholderSet = base.image == nil && self.placeholder == nil
|
|
let noImageOrPlaceholderSet = base.image == nil && self.placeholder == nil
|
|
|
if !options.keepCurrentImageWhileLoading || noImageOrPlaceholderSet {
|
|
if !options.keepCurrentImageWhileLoading || noImageOrPlaceholderSet {
|
|
@@ -82,27 +58,27 @@ extension KingfisherClass where Base: ImageView {
|
|
|
let maybeIndicator = indicator
|
|
let maybeIndicator = indicator
|
|
|
maybeIndicator?.startAnimatingView()
|
|
maybeIndicator?.startAnimatingView()
|
|
|
|
|
|
|
|
- webURL = resource.downloadURL
|
|
|
|
|
|
|
+ taskIdentifier = source.identifier
|
|
|
|
|
|
|
|
if base.shouldPreloadAllAnimation() {
|
|
if base.shouldPreloadAllAnimation() {
|
|
|
options.append(.preloadAllAnimationData)
|
|
options.append(.preloadAllAnimationData)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
let task = KingfisherManager.shared.retrieveImage(
|
|
let task = KingfisherManager.shared.retrieveImage(
|
|
|
- with: resource,
|
|
|
|
|
|
|
+ with: source,
|
|
|
options: options,
|
|
options: options,
|
|
|
progressBlock: { receivedSize, totalSize in
|
|
progressBlock: { receivedSize, totalSize in
|
|
|
- guard resource.downloadURL == self.webURL else { return }
|
|
|
|
|
|
|
+ guard source.identifier == self.taskIdentifier else { return }
|
|
|
if let progressBlock = progressBlock {
|
|
if let progressBlock = progressBlock {
|
|
|
progressBlock(receivedSize, totalSize)
|
|
progressBlock(receivedSize, totalSize)
|
|
|
}
|
|
}
|
|
|
- },
|
|
|
|
|
|
|
+ },
|
|
|
completionHandler: { result in
|
|
completionHandler: { result in
|
|
|
- DispatchQueue.main.safeAsync {
|
|
|
|
|
|
|
+ CallbackQueue.mainCurrentOrAsync.execute {
|
|
|
maybeIndicator?.stopAnimatingView()
|
|
maybeIndicator?.stopAnimatingView()
|
|
|
- guard resource.downloadURL == self.webURL else {
|
|
|
|
|
|
|
+ guard source.identifier == self.taskIdentifier else {
|
|
|
let error = KingfisherError.imageSettingError(
|
|
let error = KingfisherError.imageSettingError(
|
|
|
- reason: .notCurrentResource(result: result.value, error: result.error, resource: resource))
|
|
|
|
|
|
|
+ reason: .notCurrentSource(result: result.value, error: result.error, source: source))
|
|
|
completionHandler?(.failure(error))
|
|
completionHandler?(.failure(error))
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -111,7 +87,7 @@ extension KingfisherClass where Base: ImageView {
|
|
|
|
|
|
|
|
switch result {
|
|
switch result {
|
|
|
case .success(let value):
|
|
case .success(let value):
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
#if !os(macOS)
|
|
#if !os(macOS)
|
|
|
guard self.needsTransition(options: options, cacheType: value.cacheType) else {
|
|
guard self.needsTransition(options: options, cacheType: value.cacheType) else {
|
|
|
self.placeholder = nil
|
|
self.placeholder = nil
|
|
@@ -119,7 +95,7 @@ extension KingfisherClass where Base: ImageView {
|
|
|
completionHandler?(result)
|
|
completionHandler?(result)
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
let transition = options.transition
|
|
let transition = options.transition
|
|
|
|
|
|
|
|
// Force hiding the indicator without transition first.
|
|
// Force hiding the indicator without transition first.
|
|
@@ -138,9 +114,9 @@ extension KingfisherClass where Base: ImageView {
|
|
|
completion: { finished in
|
|
completion: { finished in
|
|
|
transition.completion?(finished)
|
|
transition.completion?(finished)
|
|
|
completionHandler?(result)
|
|
completionHandler?(result)
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
)
|
|
)
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
)
|
|
)
|
|
|
#else
|
|
#else
|
|
|
self.placeholder = nil
|
|
self.placeholder = nil
|
|
@@ -155,11 +131,52 @@ extension KingfisherClass where Base: ImageView {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
imageTask = task
|
|
imageTask = task
|
|
|
return task
|
|
return task
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /// Sets an image to the image view with a requested resource.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// - Parameters:
|
|
|
|
|
+ /// - resource: The `Resource` object contains information about the resource.
|
|
|
|
|
+ /// - placeholder: A placeholder to show while retrieving the image from the given `resource`.
|
|
|
|
|
+ /// - options: An options set to define image setting behaviors. See `KingfisherOptionsInfo` for more.
|
|
|
|
|
+ /// - progressBlock: Called when the image downloading progress gets updated. If the response does not contain an
|
|
|
|
|
+ /// `expectedContentLength`, this block will not be called.
|
|
|
|
|
+ /// - completionHandler: Called when the image retrieved and set finished.
|
|
|
|
|
+ /// - Returns: A task represents the image downloading.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// - Note:
|
|
|
|
|
+ /// This is the easist way to use Kingfisher to boost the image setting process from network. Since all parameters
|
|
|
|
|
+ /// have a default value except the `resource`, you can set an image from a certain URL to an image view like this:
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// ```
|
|
|
|
|
+ /// let url = URL(string: "https://example.com/image.png")!
|
|
|
|
|
+ /// imageView.kf.setImage(with: URL(string: url))
|
|
|
|
|
+ /// ```
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// Internally, this method will use `KingfisherManager` to get the requested resource, from either cache
|
|
|
|
|
+ /// or network. Since this method will perform UI changes, you must call it from the main thread.
|
|
|
|
|
+ /// Both `progressBlock` and `completionHandler` will be also executed in the main thread.
|
|
|
|
|
+ ///
|
|
|
|
|
+ @discardableResult
|
|
|
|
|
+ public func setImage(with resource: Resource?,
|
|
|
|
|
+ placeholder: Placeholder? = nil,
|
|
|
|
|
+ options: KingfisherOptionsInfo? = nil,
|
|
|
|
|
+ progressBlock: DownloadProgressBlock? = nil,
|
|
|
|
|
+ completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil)
|
|
|
|
|
+ -> DownloadTask?
|
|
|
|
|
+ {
|
|
|
|
|
+ return setImage(
|
|
|
|
|
+ with: resource.map { .network($0) },
|
|
|
|
|
+ placeholder: placeholder,
|
|
|
|
|
+ options: options,
|
|
|
|
|
+ progressBlock: progressBlock,
|
|
|
|
|
+ completionHandler: completionHandler)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// Cancels the image download task of the image view if it is running.
|
|
/// Cancels the image download task of the image view if it is running.
|
|
|
/// Nothing will happen if the downloading has already finished.
|
|
/// Nothing will happen if the downloading has already finished.
|
|
|
public func cancelDownloadTask() {
|
|
public func cancelDownloadTask() {
|
|
@@ -183,18 +200,17 @@ extension KingfisherClass where Base: ImageView {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Associated Object
|
|
// MARK: - Associated Object
|
|
|
-private var lastURLKey: Void?
|
|
|
|
|
|
|
+private var taskIdentifierKey: Void?
|
|
|
private var indicatorKey: Void?
|
|
private var indicatorKey: Void?
|
|
|
private var indicatorTypeKey: Void?
|
|
private var indicatorTypeKey: Void?
|
|
|
private var placeholderKey: Void?
|
|
private var placeholderKey: Void?
|
|
|
private var imageTaskKey: Void?
|
|
private var imageTaskKey: Void?
|
|
|
|
|
|
|
|
extension KingfisherClass where Base: ImageView {
|
|
extension KingfisherClass where Base: ImageView {
|
|
|
-
|
|
|
|
|
- /// Gets the image URL binded to this image view.
|
|
|
|
|
- public private(set) var webURL: URL? {
|
|
|
|
|
- get { return getAssociatedObject(base, &lastURLKey) }
|
|
|
|
|
- set { setRetainedAssociatedObject(base, &lastURLKey, newValue) }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ public internal(set) var taskIdentifier: String? {
|
|
|
|
|
+ get { return getAssociatedObject(base, &taskIdentifierKey) }
|
|
|
|
|
+ set { setRetainedAssociatedObject(base, &taskIdentifierKey, newValue) }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Holds which indicator type is going to be used.
|
|
/// Holds which indicator type is going to be used.
|