|
|
@@ -28,62 +28,47 @@
|
|
|
import AppKit
|
|
|
|
|
|
extension KingfisherClass where Base: NSButton {
|
|
|
-
|
|
|
- /// Sets an image to the button 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:
|
|
|
- /// 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: Image? = nil,
|
|
|
- options: KingfisherOptionsInfo? = nil,
|
|
|
- progressBlock: DownloadProgressBlock? = nil,
|
|
|
- completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil)
|
|
|
- -> DownloadTask?
|
|
|
+ public func setImage(
|
|
|
+ with source: Source?,
|
|
|
+ placeholder: Image? = nil,
|
|
|
+ options: KingfisherOptionsInfo? = nil,
|
|
|
+ progressBlock: DownloadProgressBlock? = nil,
|
|
|
+ completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?
|
|
|
{
|
|
|
- guard let resource = resource else {
|
|
|
+ guard let source = source else {
|
|
|
base.image = placeholder
|
|
|
- webURL = nil
|
|
|
- completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptyResource)))
|
|
|
+ taskIdentifier = nil
|
|
|
+ completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptySource)))
|
|
|
return nil
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
let options = KingfisherManager.shared.defaultOptions + (options ?? .empty)
|
|
|
if !options.keepCurrentImageWhileLoading {
|
|
|
base.image = placeholder
|
|
|
}
|
|
|
-
|
|
|
- webURL = resource.downloadURL
|
|
|
+
|
|
|
+ taskIdentifier = source.identifier
|
|
|
+
|
|
|
let task = KingfisherManager.shared.retrieveImage(
|
|
|
- with: resource,
|
|
|
+ with: source,
|
|
|
options: options,
|
|
|
progressBlock: { receivedSize, totalSize in
|
|
|
- guard resource.downloadURL == self.webURL else { return }
|
|
|
+ guard source.identifier == self.taskIdentifier else { return }
|
|
|
progressBlock?(receivedSize, totalSize)
|
|
|
- },
|
|
|
+ },
|
|
|
completionHandler: { result in
|
|
|
DispatchQueue.main.safeAsync {
|
|
|
- guard resource.downloadURL == self.webURL else {
|
|
|
+ guard source.identifier == self.taskIdentifier else {
|
|
|
let error = KingfisherError.imageSettingError(
|
|
|
- reason: .notCurrentSource(result: result.value, error: result.error, source: .network(resource)))
|
|
|
+ reason: .notCurrentSource(result: result.value, error: result.error, source: source))
|
|
|
completionHandler?(.failure(error))
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
self.imageTask = nil
|
|
|
-
|
|
|
+
|
|
|
switch result {
|
|
|
case .success(let value):
|
|
|
self.base.image = value.image
|
|
|
@@ -95,19 +80,13 @@ extension KingfisherClass where Base: NSButton {
|
|
|
completionHandler?(result)
|
|
|
}
|
|
|
}
|
|
|
- })
|
|
|
-
|
|
|
+ })
|
|
|
+
|
|
|
imageTask = task
|
|
|
return task
|
|
|
}
|
|
|
-
|
|
|
- /// Cancels the image download task of the button if it is running.
|
|
|
- /// Nothing will happen if the downloading has already finished.
|
|
|
- public func cancelImageDownloadTask() {
|
|
|
- imageTask?.cancel()
|
|
|
- }
|
|
|
-
|
|
|
- /// Sets an alternate image to the button with a requested resource.
|
|
|
+
|
|
|
+ /// Sets an image to the button with a requested resource.
|
|
|
///
|
|
|
/// - Parameters:
|
|
|
/// - resource: The `Resource` object contains information about the resource.
|
|
|
@@ -124,44 +103,66 @@ extension KingfisherClass where Base: NSButton {
|
|
|
/// Both `progressBlock` and `completionHandler` will be also executed in the main thread.
|
|
|
///
|
|
|
@discardableResult
|
|
|
- public func setAlternateImage(with resource: Resource?,
|
|
|
- placeholder: Image? = nil,
|
|
|
- options: KingfisherOptionsInfo? = nil,
|
|
|
- progressBlock: DownloadProgressBlock? = nil,
|
|
|
- completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil)
|
|
|
- -> DownloadTask?
|
|
|
+ public func setImage(
|
|
|
+ with resource: Resource?,
|
|
|
+ placeholder: Image? = 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 button if it is running.
|
|
|
+ /// Nothing will happen if the downloading has already finished.
|
|
|
+ public func cancelImageDownloadTask() {
|
|
|
+ imageTask?.cancel()
|
|
|
+ }
|
|
|
+
|
|
|
+ @discardableResult
|
|
|
+ public func setAlternateImage(
|
|
|
+ with source: Source?,
|
|
|
+ placeholder: Image? = nil,
|
|
|
+ options: KingfisherOptionsInfo? = nil,
|
|
|
+ progressBlock: DownloadProgressBlock? = nil,
|
|
|
+ completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?
|
|
|
{
|
|
|
- guard let resource = resource else {
|
|
|
+ guard let source = source else {
|
|
|
base.alternateImage = placeholder
|
|
|
- alternateWebURL = nil
|
|
|
- completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptyResource)))
|
|
|
+ alternateTaskIdentifier = nil
|
|
|
+ completionHandler?(.failure(KingfisherError.imageSettingError(reason: .emptySource)))
|
|
|
return nil
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
let options = KingfisherManager.shared.defaultOptions + (options ?? .empty)
|
|
|
if !options.keepCurrentImageWhileLoading {
|
|
|
base.alternateImage = placeholder
|
|
|
}
|
|
|
-
|
|
|
- alternateWebURL = resource.downloadURL
|
|
|
+
|
|
|
+ alternateTaskIdentifier = source.identifier
|
|
|
let task = KingfisherManager.shared.retrieveImage(
|
|
|
- with: resource,
|
|
|
+ with: source,
|
|
|
options: options,
|
|
|
progressBlock: { receivedSize, totalSize in
|
|
|
- guard resource.downloadURL == self.alternateWebURL else { return }
|
|
|
+ guard self.alternateTaskIdentifier == source.identifier else { return }
|
|
|
progressBlock?(receivedSize, totalSize)
|
|
|
},
|
|
|
completionHandler: { result in
|
|
|
- DispatchQueue.main.safeAsync {
|
|
|
- guard resource.downloadURL == self.alternateWebURL else {
|
|
|
+ CallbackQueue.mainCurrentOrAsync.execute {
|
|
|
+ guard self.alternateTaskIdentifier == source.identifier else {
|
|
|
let error = KingfisherError.imageSettingError(
|
|
|
- reason: .notCurrentSource(result: result.value, error: result.error, source: .network(resource)))
|
|
|
+ reason: .notCurrentSource(result: result.value, error: result.error, source: source))
|
|
|
completionHandler?(.failure(error))
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
self.alternateImageTask = nil
|
|
|
-
|
|
|
+
|
|
|
switch result {
|
|
|
case .success(let value):
|
|
|
self.base.alternateImage = value.image
|
|
|
@@ -173,12 +174,43 @@ extension KingfisherClass where Base: NSButton {
|
|
|
completionHandler?(result)
|
|
|
}
|
|
|
}
|
|
|
- })
|
|
|
-
|
|
|
+ })
|
|
|
+
|
|
|
alternateImageTask = task
|
|
|
return task
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /// Sets an alternate image to the button 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:
|
|
|
+ /// 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 setAlternateImage(
|
|
|
+ with resource: Resource?,
|
|
|
+ placeholder: Image? = nil,
|
|
|
+ options: KingfisherOptionsInfo? = nil,
|
|
|
+ progressBlock: DownloadProgressBlock? = nil,
|
|
|
+ completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?
|
|
|
+ {
|
|
|
+ return setAlternateImage(
|
|
|
+ with: resource.map { .network($0) },
|
|
|
+ placeholder: placeholder,
|
|
|
+ options: options,
|
|
|
+ progressBlock: progressBlock,
|
|
|
+ completionHandler: completionHandler)
|
|
|
+ }
|
|
|
|
|
|
/// Cancels the alternate image download task of the button if it is running.
|
|
|
/// Nothing will happen if the downloading has already finished.
|
|
|
@@ -189,34 +221,49 @@ extension KingfisherClass where Base: NSButton {
|
|
|
|
|
|
|
|
|
// MARK: - Associated Object
|
|
|
-private var lastURLKey: Void?
|
|
|
+private var taskIdentifierKey: Void?
|
|
|
private var imageTaskKey: Void?
|
|
|
|
|
|
-private var lastAlternateURLKey: Void?
|
|
|
+private var alternateTaskIdentifierKey: Void?
|
|
|
private var alternateImageTaskKey: Void?
|
|
|
|
|
|
extension KingfisherClass where Base: NSButton {
|
|
|
-
|
|
|
- /// Gets the image URL binded to this button.
|
|
|
- public private(set) var webURL: URL? {
|
|
|
- get { return getAssociatedObject(base, &lastURLKey) }
|
|
|
- set { setRetainedAssociatedObject(base, &lastURLKey, newValue) }
|
|
|
+
|
|
|
+ public private(set) var taskIdentifier: String? {
|
|
|
+ get { return getAssociatedObject(base, &taskIdentifierKey) }
|
|
|
+ set { setRetainedAssociatedObject(base, &taskIdentifierKey, newValue) }
|
|
|
}
|
|
|
|
|
|
private var imageTask: DownloadTask? {
|
|
|
get { return getAssociatedObject(base, &imageTaskKey) }
|
|
|
set { setRetainedAssociatedObject(base, &imageTaskKey, newValue)}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- /// Gets the image URL binded to this button.
|
|
|
- public private(set) var alternateWebURL: URL? {
|
|
|
- get { return getAssociatedObject(base, &lastAlternateURLKey) }
|
|
|
- set { setRetainedAssociatedObject(base, &lastAlternateURLKey, newValue) }
|
|
|
+
|
|
|
+ public private(set) var alternateTaskIdentifier: String? {
|
|
|
+ get { return getAssociatedObject(base, &alternateTaskIdentifierKey) }
|
|
|
+ set { setRetainedAssociatedObject(base, &alternateTaskIdentifierKey, newValue) }
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private var alternateImageTask: DownloadTask? {
|
|
|
get { return getAssociatedObject(base, &alternateImageTaskKey) }
|
|
|
set { setRetainedAssociatedObject(base, &alternateImageTaskKey, newValue)}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+extension KingfisherClass where Base: NSButton {
|
|
|
+
|
|
|
+ /// Gets the image URL binded to this button.
|
|
|
+ @available(*, deprecated, message: "Use `taskIdentifier` instead.", renamed: "taskIdentifier")
|
|
|
+ public private(set) var webURL: URL? {
|
|
|
+ get { return taskIdentifier.flatMap { URL(string: $0) } }
|
|
|
+ set { taskIdentifier = newValue?.absoluteString }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /// Gets the image URL binded to this button.
|
|
|
+ @available(*, deprecated, message: "Use `alternateTaskIdentifier` instead.", renamed: "alternateTaskIdentifier")
|
|
|
+ public private(set) var alternateWebURL: URL? {
|
|
|
+ get { return alternateTaskIdentifier.flatMap { URL(string: $0) } }
|
|
|
+ set { alternateTaskIdentifier = newValue?.absoluteString }
|
|
|
+ }
|
|
|
+}
|