UIButton+Kingfisher.swift 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. //
  2. // UIButton+Kingfisher.swift
  3. // Kingfisher
  4. //
  5. // Created by Wei Wang on 15/4/13.
  6. //
  7. // Copyright (c) 2016 Wei Wang <onevcat@gmail.com>
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. #if os(iOS) || os(tvOS)
  27. import UIKit
  28. /**
  29. * Set image to use from web for a specified state.
  30. */
  31. extension UIButton {
  32. /**
  33. Set an image to use for a specified state with a resource.
  34. It will ask for Kingfisher's manager to get the image for the `cacheKey` property in `resource` and then set it for a button state.
  35. The memory and disk will be searched first. If the manager does not find it, it will try to download the image at the `resource.downloadURL` and store it with `resource.cacheKey` for next use.
  36. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  37. - parameter state: The state that uses the specified image.
  38. - returns: A task represents the retrieving process.
  39. */
  40. public func kf_setImageWithResource(resource: Resource,
  41. forState state: UIControlState) -> RetrieveImageTask
  42. {
  43. return kf_setImageWithResource(resource, forState: state, placeholderImage: nil, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  44. }
  45. /**
  46. Set an image to use for a specified state with a URL.
  47. It will ask for Kingfisher's manager to get the image for the URL and then set it for a button state.
  48. The memory and disk will be searched first with `URL.absoluteString` as the cache key. If the manager does not find it, it will try to download the image at this URL and store the image with `URL.absoluteString` as cache key for next use.
  49. If you need to specify the key other than `URL.absoluteString`, please use resource version of these APIs with `resource.cacheKey` set to what you want.
  50. - parameter URL: The URL of image for specified state.
  51. - parameter state: The state that uses the specified image.
  52. - returns: A task represents the retrieving process.
  53. */
  54. public func kf_setImageWithURL(URL: NSURL,
  55. forState state: UIControlState) -> RetrieveImageTask
  56. {
  57. return kf_setImageWithURL(URL, forState: state, placeholderImage: nil, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  58. }
  59. /**
  60. Set an image to use for a specified state with a resource and a placeholder image.
  61. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  62. - parameter state: The state that uses the specified image.
  63. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  64. - returns: A task represents the retrieving process.
  65. */
  66. public func kf_setImageWithResource(resource: Resource,
  67. forState state: UIControlState,
  68. placeholderImage: UIImage?) -> RetrieveImageTask
  69. {
  70. return kf_setImageWithResource(resource, forState: state, placeholderImage: placeholderImage, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  71. }
  72. /**
  73. Set an image to use for a specified state with a URL and a placeholder image.
  74. - parameter URL: The URL of image for specified state.
  75. - parameter state: The state that uses the specified image.
  76. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  77. - returns: A task represents the retrieving process.
  78. */
  79. public func kf_setImageWithURL(URL: NSURL,
  80. forState state: UIControlState,
  81. placeholderImage: UIImage?) -> RetrieveImageTask
  82. {
  83. return kf_setImageWithURL(URL, forState: state, placeholderImage: placeholderImage, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  84. }
  85. /**
  86. Set an image to use for a specified state with a resource, a placeholder image and options.
  87. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  88. - parameter state: The state that uses the specified image.
  89. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  90. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  91. - returns: A task represents the retrieving process.
  92. */
  93. public func kf_setImageWithResource(resource: Resource,
  94. forState state: UIControlState,
  95. placeholderImage: UIImage?,
  96. optionsInfo: KingfisherOptionsInfo?) -> RetrieveImageTask
  97. {
  98. return kf_setImageWithResource(resource, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: nil)
  99. }
  100. /**
  101. Set an image to use for a specified state with a URL, a placeholder image and options.
  102. - parameter URL: The URL of image for specified state.
  103. - parameter state: The state that uses the specified image.
  104. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  105. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  106. - returns: A task represents the retrieving process.
  107. */
  108. public func kf_setImageWithURL(URL: NSURL,
  109. forState state: UIControlState,
  110. placeholderImage: UIImage?,
  111. optionsInfo: KingfisherOptionsInfo?) -> RetrieveImageTask
  112. {
  113. return kf_setImageWithURL(URL, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: nil)
  114. }
  115. /**
  116. Set an image to use for a specified state with a resource, a placeholder image, options and completion handler.
  117. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  118. - parameter state: The state that uses the specified image.
  119. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  120. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  121. - parameter completionHandler: Called when the image retrieved and set.
  122. - returns: A task represents the retrieving process.
  123. */
  124. public func kf_setImageWithResource(resource: Resource,
  125. forState state: UIControlState,
  126. placeholderImage: UIImage?,
  127. optionsInfo: KingfisherOptionsInfo?,
  128. completionHandler: CompletionHandler?) -> RetrieveImageTask
  129. {
  130. return kf_setImageWithResource(resource, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: completionHandler)
  131. }
  132. /**
  133. Set an image to use for a specified state with a URL, a placeholder image, options and completion handler.
  134. - parameter URL: The URL of image for specified state.
  135. - parameter state: The state that uses the specified image.
  136. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  137. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  138. - parameter completionHandler: Called when the image retrieved and set.
  139. - returns: A task represents the retrieving process.
  140. */
  141. public func kf_setImageWithURL(URL: NSURL,
  142. forState state: UIControlState,
  143. placeholderImage: UIImage?,
  144. optionsInfo: KingfisherOptionsInfo?,
  145. completionHandler: CompletionHandler?) -> RetrieveImageTask
  146. {
  147. return kf_setImageWithURL(URL, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: completionHandler)
  148. }
  149. /**
  150. Set an image to use for a specified state with a resource, a placeholder image, options, progress handler and completion handler.
  151. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  152. - parameter state: The state that uses the specified image.
  153. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  154. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  155. - parameter progressBlock: Called when the image downloading progress gets updated.
  156. - parameter completionHandler: Called when the image retrieved and set.
  157. - returns: A task represents the retrieving process.
  158. */
  159. public func kf_setImageWithResource(resource: Resource,
  160. forState state: UIControlState,
  161. placeholderImage: UIImage?,
  162. optionsInfo: KingfisherOptionsInfo?,
  163. progressBlock: DownloadProgressBlock?,
  164. completionHandler: CompletionHandler?) -> RetrieveImageTask
  165. {
  166. setImage(placeholderImage, forState: state)
  167. kf_setWebURL(resource.downloadURL, forState: state)
  168. let task = KingfisherManager.sharedManager.retrieveImageWithResource(resource, optionsInfo: optionsInfo,
  169. progressBlock: { receivedSize, totalSize in
  170. if let progressBlock = progressBlock {
  171. dispatch_async(dispatch_get_main_queue(), { () -> Void in
  172. progressBlock(receivedSize: receivedSize, totalSize: totalSize)
  173. })
  174. }
  175. },
  176. completionHandler: {[weak self] image, error, cacheType, imageURL in
  177. dispatch_async_safely_main_queue {
  178. if let sSelf = self {
  179. sSelf.kf_setImageTask(nil)
  180. if imageURL == sSelf.kf_webURLForState(state) && image != nil {
  181. sSelf.setImage(image, forState: state)
  182. }
  183. completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
  184. }
  185. }
  186. })
  187. kf_setImageTask(task)
  188. return task
  189. }
  190. /**
  191. Set an image to use for a specified state with a URL, a placeholder image, options, progress handler and completion handler.
  192. - parameter URL: The URL of image for specified state.
  193. - parameter state: The state that uses the specified image.
  194. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  195. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  196. - parameter progressBlock: Called when the image downloading progress gets updated.
  197. - parameter completionHandler: Called when the image retrieved and set.
  198. - returns: A task represents the retrieving process.
  199. */
  200. public func kf_setImageWithURL(URL: NSURL,
  201. forState state: UIControlState,
  202. placeholderImage: UIImage?,
  203. optionsInfo: KingfisherOptionsInfo?,
  204. progressBlock: DownloadProgressBlock?,
  205. completionHandler: CompletionHandler?) -> RetrieveImageTask
  206. {
  207. return kf_setImageWithResource(Resource(downloadURL: URL),
  208. forState: state,
  209. placeholderImage: placeholderImage,
  210. optionsInfo: optionsInfo,
  211. progressBlock: progressBlock,
  212. completionHandler: completionHandler)
  213. }
  214. }
  215. private var lastURLKey: Void?
  216. private var imageTaskKey: Void?
  217. // MARK: - Runtime for UIButton image
  218. extension UIButton {
  219. /**
  220. Get the image URL binded to this button for a specified state.
  221. - parameter state: The state that uses the specified image.
  222. - returns: Current URL for image.
  223. */
  224. public func kf_webURLForState(state: UIControlState) -> NSURL? {
  225. return kf_webURLs[NSNumber(unsignedLong:state.rawValue)] as? NSURL
  226. }
  227. private func kf_setWebURL(URL: NSURL, forState state: UIControlState) {
  228. kf_webURLs[NSNumber(unsignedLong:state.rawValue)] = URL
  229. }
  230. private var kf_webURLs: NSMutableDictionary {
  231. var dictionary = objc_getAssociatedObject(self, &lastURLKey) as? NSMutableDictionary
  232. if dictionary == nil {
  233. dictionary = NSMutableDictionary()
  234. kf_setWebURLs(dictionary!)
  235. }
  236. return dictionary!
  237. }
  238. private func kf_setWebURLs(URLs: NSMutableDictionary) {
  239. objc_setAssociatedObject(self, &lastURLKey, URLs, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  240. }
  241. private var kf_imageTask: RetrieveImageTask? {
  242. return objc_getAssociatedObject(self, &imageTaskKey) as? RetrieveImageTask
  243. }
  244. private func kf_setImageTask(task: RetrieveImageTask?) {
  245. objc_setAssociatedObject(self, &imageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  246. }
  247. }
  248. /**
  249. * Set background image to use from web for a specified state.
  250. */
  251. extension UIButton {
  252. /**
  253. Set the background image to use for a specified state with a resource.
  254. It will ask for Kingfisher's manager to get the image for the `cacheKey` property in `resource` and then set it for a button state.
  255. The memory and disk will be searched first. If the manager does not find it, it will try to download the image at the `resource.downloadURL` and store it with `resource.cacheKey` for next use.
  256. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  257. - parameter state: The state that uses the specified image.
  258. - returns: A task represents the retrieving process.
  259. */
  260. public func kf_setBackgroundImageWithResource(resource: Resource,
  261. forState state: UIControlState) -> RetrieveImageTask
  262. {
  263. return kf_setBackgroundImageWithResource(resource, forState: state, placeholderImage: nil, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  264. }
  265. /**
  266. Set the background image to use for a specified state with a URL.
  267. It will ask for Kingfisher's manager to get the image for the URL and then set it for a button state.
  268. The memory and disk will be searched first with `URL.absoluteString` as the cache key. If the manager does not find it, it will try to download the image at this URL and store the image with `URL.absoluteString` as cache key for next use.
  269. If you need to specify the key other than `URL.absoluteString`, please use resource version of these APIs with `resource.cacheKey` set to what you want.
  270. - parameter URL: The URL of image for specified state.
  271. - parameter state: The state that uses the specified image.
  272. - returns: A task represents the retrieving process.
  273. */
  274. public func kf_setBackgroundImageWithURL(URL: NSURL,
  275. forState state: UIControlState) -> RetrieveImageTask
  276. {
  277. return kf_setBackgroundImageWithURL(URL, forState: state, placeholderImage: nil, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  278. }
  279. /**
  280. Set the background image to use for a specified state with a resource and a placeholder image.
  281. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  282. - parameter state: The state that uses the specified image.
  283. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  284. - returns: A task represents the retrieving process.
  285. */
  286. public func kf_setBackgroundImageWithResource(resource: Resource,
  287. forState state: UIControlState,
  288. placeholderImage: UIImage?) -> RetrieveImageTask
  289. {
  290. return kf_setBackgroundImageWithResource(resource, forState: state, placeholderImage: placeholderImage, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  291. }
  292. /**
  293. Set the background image to use for a specified state with a URL and a placeholder image.
  294. - parameter URL: The URL of image for specified state.
  295. - parameter state: The state that uses the specified image.
  296. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  297. - returns: A task represents the retrieving process.
  298. */
  299. public func kf_setBackgroundImageWithURL(URL: NSURL,
  300. forState state: UIControlState,
  301. placeholderImage: UIImage?) -> RetrieveImageTask
  302. {
  303. return kf_setBackgroundImageWithURL(URL, forState: state, placeholderImage: placeholderImage, optionsInfo: nil, progressBlock: nil, completionHandler: nil)
  304. }
  305. /**
  306. Set the background image to use for a specified state with a resource, a placeholder image and options.
  307. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  308. - parameter state: The state that uses the specified image.
  309. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  310. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  311. - returns: A task represents the retrieving process.
  312. */
  313. public func kf_setBackgroundImageWithResource(resource: Resource,
  314. forState state: UIControlState,
  315. placeholderImage: UIImage?,
  316. optionsInfo: KingfisherOptionsInfo?) -> RetrieveImageTask
  317. {
  318. return kf_setBackgroundImageWithResource(resource, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: nil)
  319. }
  320. /**
  321. Set the background image to use for a specified state with a URL, a placeholder image and options.
  322. - parameter URL: The URL of image for specified state.
  323. - parameter state: The state that uses the specified image.
  324. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  325. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  326. - returns: A task represents the retrieving process.
  327. */
  328. public func kf_setBackgroundImageWithURL(URL: NSURL,
  329. forState state: UIControlState,
  330. placeholderImage: UIImage?,
  331. optionsInfo: KingfisherOptionsInfo?) -> RetrieveImageTask
  332. {
  333. return kf_setBackgroundImageWithURL(URL, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: nil)
  334. }
  335. /**
  336. Set the background image to use for a specified state with a resource, a placeholder image, options and completion handler.
  337. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  338. - parameter state: The state that uses the specified image.
  339. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  340. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  341. - parameter completionHandler: Called when the image retrieved and set.
  342. - returns: A task represents the retrieving process.
  343. */
  344. public func kf_setBackgroundImageWithResource(resource: Resource,
  345. forState state: UIControlState,
  346. placeholderImage: UIImage?,
  347. optionsInfo: KingfisherOptionsInfo?,
  348. completionHandler: CompletionHandler?) -> RetrieveImageTask
  349. {
  350. return kf_setBackgroundImageWithResource(resource, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: completionHandler)
  351. }
  352. /**
  353. Set the background image to use for a specified state with a URL, a placeholder image, options and completion handler.
  354. - parameter URL: The URL of image for specified state.
  355. - parameter state: The state that uses the specified image.
  356. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  357. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  358. - parameter completionHandler: Called when the image retrieved and set.
  359. - returns: A task represents the retrieving process.
  360. */
  361. public func kf_setBackgroundImageWithURL(URL: NSURL,
  362. forState state: UIControlState,
  363. placeholderImage: UIImage?,
  364. optionsInfo: KingfisherOptionsInfo?,
  365. completionHandler: CompletionHandler?) -> RetrieveImageTask
  366. {
  367. return kf_setBackgroundImageWithURL(URL, forState: state, placeholderImage: placeholderImage, optionsInfo: optionsInfo, progressBlock: nil, completionHandler: completionHandler)
  368. }
  369. /**
  370. Set the background image to use for a specified state with a resource,
  371. a placeholder image, options progress handler and completion handler.
  372. - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`.
  373. - parameter state: The state that uses the specified image.
  374. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  375. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  376. - parameter progressBlock: Called when the image downloading progress gets updated.
  377. - parameter completionHandler: Called when the image retrieved and set.
  378. - returns: A task represents the retrieving process.
  379. */
  380. public func kf_setBackgroundImageWithResource(resource: Resource,
  381. forState state: UIControlState,
  382. placeholderImage: UIImage?,
  383. optionsInfo: KingfisherOptionsInfo?,
  384. progressBlock: DownloadProgressBlock?,
  385. completionHandler: CompletionHandler?) -> RetrieveImageTask
  386. {
  387. setBackgroundImage(placeholderImage, forState: state)
  388. kf_setBackgroundWebURL(resource.downloadURL, forState: state)
  389. let task = KingfisherManager.sharedManager.retrieveImageWithResource(resource, optionsInfo: optionsInfo,
  390. progressBlock: { receivedSize, totalSize in
  391. if let progressBlock = progressBlock {
  392. dispatch_async(dispatch_get_main_queue(), { () -> Void in
  393. progressBlock(receivedSize: receivedSize, totalSize: totalSize)
  394. })
  395. }
  396. },
  397. completionHandler: { [weak self] image, error, cacheType, imageURL in
  398. dispatch_async_safely_main_queue {
  399. if let sSelf = self {
  400. sSelf.kf_setBackgroundImageTask(nil)
  401. if imageURL == sSelf.kf_backgroundWebURLForState(state) && image != nil {
  402. sSelf.setBackgroundImage(image, forState: state)
  403. }
  404. completionHandler?(image: image, error: error, cacheType: cacheType, imageURL: imageURL)
  405. }
  406. }
  407. })
  408. kf_setBackgroundImageTask(task)
  409. return task
  410. }
  411. /**
  412. Set the background image to use for a specified state with a URL,
  413. a placeholder image, options progress handler and completion handler.
  414. - parameter URL: The URL of image for specified state.
  415. - parameter state: The state that uses the specified image.
  416. - parameter placeholderImage: A placeholder image when retrieving the image at URL.
  417. - parameter optionsInfo: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more.
  418. - parameter progressBlock: Called when the image downloading progress gets updated.
  419. - parameter completionHandler: Called when the image retrieved and set.
  420. - returns: A task represents the retrieving process.
  421. */
  422. public func kf_setBackgroundImageWithURL(URL: NSURL,
  423. forState state: UIControlState,
  424. placeholderImage: UIImage?,
  425. optionsInfo: KingfisherOptionsInfo?,
  426. progressBlock: DownloadProgressBlock?,
  427. completionHandler: CompletionHandler?) -> RetrieveImageTask
  428. {
  429. return kf_setBackgroundImageWithResource(Resource(downloadURL: URL),
  430. forState: state,
  431. placeholderImage: placeholderImage,
  432. optionsInfo: optionsInfo,
  433. progressBlock: progressBlock,
  434. completionHandler: completionHandler)
  435. }
  436. }
  437. private var lastBackgroundURLKey: Void?
  438. private var backgroundImageTaskKey: Void?
  439. // MARK: - Runtime for UIButton background image
  440. extension UIButton {
  441. /**
  442. Get the background image URL binded to this button for a specified state.
  443. - parameter state: The state that uses the specified background image.
  444. - returns: Current URL for background image.
  445. */
  446. public func kf_backgroundWebURLForState(state: UIControlState) -> NSURL? {
  447. return kf_backgroundWebURLs[NSNumber(unsignedLong:state.rawValue)] as? NSURL
  448. }
  449. private func kf_setBackgroundWebURL(URL: NSURL, forState state: UIControlState) {
  450. kf_backgroundWebURLs[NSNumber(unsignedLong:state.rawValue)] = URL
  451. }
  452. private var kf_backgroundWebURLs: NSMutableDictionary {
  453. var dictionary = objc_getAssociatedObject(self, &lastBackgroundURLKey) as? NSMutableDictionary
  454. if dictionary == nil {
  455. dictionary = NSMutableDictionary()
  456. kf_setBackgroundWebURLs(dictionary!)
  457. }
  458. return dictionary!
  459. }
  460. private func kf_setBackgroundWebURLs(URLs: NSMutableDictionary) {
  461. objc_setAssociatedObject(self, &lastBackgroundURLKey, URLs, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  462. }
  463. private var kf_backgroundImageTask: RetrieveImageTask? {
  464. return objc_getAssociatedObject(self, &backgroundImageTaskKey) as? RetrieveImageTask
  465. }
  466. private func kf_setBackgroundImageTask(task: RetrieveImageTask?) {
  467. objc_setAssociatedObject(self, &backgroundImageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  468. }
  469. }
  470. // MARK: - Cancel image download tasks.
  471. extension UIButton {
  472. /**
  473. Cancel the image download task bounded to the image view if it is running.
  474. Nothing will happen if the downloading has already finished.
  475. */
  476. public func kf_cancelImageDownloadTask() {
  477. kf_imageTask?.downloadTask?.cancel()
  478. }
  479. /**
  480. Cancel the background image download task bounded to the image view if it is running.
  481. Nothing will happen if the downloading has already finished.
  482. */
  483. public func kf_cancelBackgroundImageDownloadTask() {
  484. kf_backgroundImageTask?.downloadTask?.cancel()
  485. }
  486. }
  487. #elseif os(OSX)
  488. import AppKit
  489. extension NSButton {
  490. // Not Implemented yet.
  491. }
  492. #endif