Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
//
2
//  UIButton+AlamofireImage.swift
3
//
4
//  Copyright (c) 2015 Alamofire Software Foundation (http://alamofire.org/)
5
//
6
//  Permission is hereby granted, free of charge, to any person obtaining a copy
7
//  of this software and associated documentation files (the "Software"), to deal
8
//  in the Software without restriction, including without limitation the rights
9
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
//  copies of the Software, and to permit persons to whom the Software is
11
//  furnished to do so, subject to the following conditions:
12
//
13
//  The above copyright notice and this permission notice shall be included in
14
//  all copies or substantial portions of the Software.
15
//
16
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
//  THE SOFTWARE.
23
//
24
 
25
import Alamofire
26
import Foundation
27
 
28
#if os(iOS) || os(tvOS)
29
 
30
import UIKit
31
 
32
public typealias ControlState = UIControl.State
33
 
34
extension UIButton: AlamofireExtended {}
35
extension AlamofireExtension where ExtendedType: UIButton {
36
    // MARK: - Properties
37
 
38
    /// The instance image downloader used to download all images. If this property is `nil`, the `UIButton` will
39
    /// fallback on the `sharedImageDownloader` for all downloads. The most common use case for needing to use a
40
    /// custom instance image downloader is when images are behind different basic auth credentials.
41
    public var imageDownloader: ImageDownloader? {
42
        get {
43
            objc_getAssociatedObject(type, &AssociatedKeys.imageDownloader) as? ImageDownloader
44
        }
45
        nonmutating set {
46
            objc_setAssociatedObject(type, &AssociatedKeys.imageDownloader, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
47
        }
48
    }
49
 
50
    /// The shared image downloader used to download all images. By default, this is the default `ImageDownloader`
51
    /// instance backed with an `AutoPurgingImageCache` which automatically evicts images from the cache when the memory
52
    /// capacity is reached or memory warning notifications occur. The shared image downloader is only used if the
53
    /// `imageDownloader` is `nil`.
54
    public static var sharedImageDownloader: ImageDownloader {
55
        get {
56
            guard let
57
                downloader = objc_getAssociatedObject(UIButton.self, &AssociatedKeys.sharedImageDownloader) as? ImageDownloader
58
            else { return ImageDownloader.default }
59
 
60
            return downloader
61
        }
62
        set {
63
            objc_setAssociatedObject(UIButton.self, &AssociatedKeys.sharedImageDownloader, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
64
        }
65
    }
66
 
67
    private var imageRequestReceipts: [UInt: RequestReceipt] {
68
        get {
69
            guard let
70
                receipts = objc_getAssociatedObject(type, &AssociatedKeys.imageReceipts) as? [UInt: RequestReceipt]
71
            else { return [:] }
72
 
73
            return receipts
74
        }
75
        nonmutating set {
76
            objc_setAssociatedObject(type, &AssociatedKeys.imageReceipts, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
77
        }
78
    }
79
 
80
    private var backgroundImageRequestReceipts: [UInt: RequestReceipt] {
81
        get {
82
            guard let
83
                receipts = objc_getAssociatedObject(type, &AssociatedKeys.backgroundImageReceipts) as? [UInt: RequestReceipt]
84
            else { return [:] }
85
 
86
            return receipts
87
        }
88
        nonmutating set {
89
            objc_setAssociatedObject(type, &AssociatedKeys.backgroundImageReceipts, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
90
        }
91
    }
92
 
93
    // MARK: - Image Downloads
94
 
95
    /// Asynchronously downloads an image from the specified URL and sets it once the request is finished.
96
    ///
97
    /// If the image is cached locally, the image is set immediately. Otherwise the specified placeholder image will be
98
    /// set immediately, and then the remote image will be set once the image request is finished.
99
    ///
100
    /// - parameter state:            The control state of the button to set the image on.
101
    /// - parameter url:              The URL used for your image request.
102
    /// - parameter cacheKey:         An optional key used to identify the image in the cache. Defaults to `nil`.
103
    /// - parameter placeholderImage: The image to be set initially until the image request finished. If `nil`, the
104
    ///                               image will not change its image until the image request finishes. Defaults
105
    ///                               to `nil`.
106
    /// - parameter serializer:       Image response serializer used to convert the image data to `UIImage`. Defaults
107
    ///                               to `nil` which will fall back to the instance `imageResponseSerializer` set on
108
    ///                               the `ImageDownloader`.
109
    /// - parameter filter:           The image filter applied to the image after the image request is finished.
110
    ///                               Defaults to `nil`.
111
    /// - parameter progress:         The closure to be executed periodically during the lifecycle of the request.
112
    ///                               Defaults to `nil`.
113
    /// - parameter progressQueue:    The dispatch queue to call the progress closure on. Defaults to the main queue.
114
    /// - parameter completion:       A closure to be executed when the image request finishes. The closure takes a
115
    ///                               single response value containing either the image or the error that occurred. If
116
    ///                               the image was returned from the image cache, the response will be `nil`. Defaults
117
    ///                               to `nil`.
118
    public func setImage(for state: ControlState,
119
                         url: URL,
120
                         cacheKey: String? = nil,
121
                         placeholderImage: UIImage? = nil,
122
                         serializer: ImageResponseSerializer? = nil,
123
                         filter: ImageFilter? = nil,
124
                         progress: ImageDownloader.ProgressHandler? = nil,
125
                         progressQueue: DispatchQueue = DispatchQueue.main,
126
                         completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
127
        setImage(for: state,
128
                 urlRequest: urlRequest(with: url),
129
                 cacheKey: cacheKey,
130
                 placeholderImage: placeholderImage,
131
                 serializer: serializer,
132
                 filter: filter,
133
                 progress: progress,
134
                 progressQueue: progressQueue,
135
                 completion: completion)
136
    }
137
 
138
    /// Asynchronously downloads an image from the specified URL and sets it once the request is finished.
139
    ///
140
    /// If the image is cached locally, the image is set immediately. Otherwise the specified placeholder image will be
141
    /// set immediately, and then the remote image will be set once the image request is finished.
142
    ///
143
    /// - parameter state:            The control state of the button to set the image on.
144
    /// - parameter urlRequest:       The URL request.
145
    /// - parameter cacheKey:         An optional key used to identify the image in the cache. Defaults to `nil`.
146
    /// - parameter placeholderImage: The image to be set initially until the image request finished. If `nil`, the
147
    ///                               image will not change its image until the image request finishes. Defaults
148
    ///                               to `nil`.
149
    /// - parameter serializer:       Image response serializer used to convert the image data to `UIImage`. Defaults
150
    ///                               to `nil` which will fall back to the instance `imageResponseSerializer` set on
151
    ///                               the `ImageDownloader`.
152
    /// - parameter filter:           The image filter applied to the image after the image request is finished.
153
    ///                               Defaults to `nil`.
154
    /// - parameter progress:         The closure to be executed periodically during the lifecycle of the request.
155
    ///                               Defaults to `nil`.
156
    /// - parameter progressQueue:    The dispatch queue to call the progress closure on. Defaults to the main queue.
157
    /// - parameter completion:       A closure to be executed when the image request finishes. The closure takes a
158
    ///                               single response value containing either the image or the error that occurred. If
159
    ///                               the image was returned from the image cache, the response will be `nil`. Defaults
160
    ///                               to `nil`.
161
    public func setImage(for state: ControlState,
162
                         urlRequest: URLRequestConvertible,
163
                         cacheKey: String? = nil,
164
                         placeholderImage: UIImage? = nil,
165
                         serializer: ImageResponseSerializer? = nil,
166
                         filter: ImageFilter? = nil,
167
                         progress: ImageDownloader.ProgressHandler? = nil,
168
                         progressQueue: DispatchQueue = DispatchQueue.main,
169
                         completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
170
        guard !isImageURLRequest(urlRequest, equalToActiveRequestURLForState: state) else {
171
            let response = AFIDataResponse<UIImage>(request: nil,
172
                                                    response: nil,
173
                                                    data: nil,
174
                                                    metrics: nil,
175
                                                    serializationDuration: 0.0,
176
                                                    result: .failure(AFIError.requestCancelled))
177
 
178
            completion?(response)
179
 
180
            return
181
        }
182
 
183
        cancelImageRequest(for: state)
184
 
185
        let imageDownloader = self.imageDownloader ?? UIButton.af.sharedImageDownloader
186
        let imageCache = imageDownloader.imageCache
187
 
188
        // Use the image from the image cache if it exists
189
        if let request = urlRequest.urlRequest {
190
            let cachedImage: Image?
191
 
192
            if let cacheKey = cacheKey {
193
                cachedImage = imageCache?.image(withIdentifier: cacheKey)
194
            } else {
195
                cachedImage = imageCache?.image(for: request, withIdentifier: filter?.identifier)
196
            }
197
 
198
            if let image = cachedImage {
199
                let response = AFIDataResponse<UIImage>(request: urlRequest.urlRequest,
200
                                                        response: nil,
201
                                                        data: nil,
202
                                                        metrics: nil,
203
                                                        serializationDuration: 0.0,
204
                                                        result: .success(image))
205
 
206
                type.setImage(image, for: state)
207
                completion?(response)
208
 
209
                return
210
            }
211
        }
212
 
213
        // Set the placeholder since we're going to have to download
214
        if let placeholderImage = placeholderImage { type.setImage(placeholderImage, for: state) }
215
 
216
        // Generate a unique download id to check whether the active request has changed while downloading
217
        let downloadID = UUID().uuidString
218
 
219
        // Weakify the button to allow it to go out-of-memory while download is running if deallocated
220
        weak var button = type
221
 
222
        // Download the image, then set the image for the control state
223
        let requestReceipt = imageDownloader.download(urlRequest,
224
                                                      cacheKey: cacheKey,
225
                                                      receiptID: downloadID,
226
                                                      serializer: serializer,
227
                                                      filter: filter,
228
                                                      progress: progress,
229
                                                      progressQueue: progressQueue,
230
                                                      completion: { response in
231
                                                          guard
232
                                                              let strongSelf = button?.af,
233
                                                              strongSelf.isImageURLRequest(response.request, equalToActiveRequestURLForState: state) &&
234
                                                              strongSelf.imageRequestReceipt(for: state)?.receiptID == downloadID
235
                                                          else {
236
                                                              completion?(response)
237
                                                              return
238
                                                          }
239
 
240
                                                          if case let .success(image) = response.result {
241
                                                              strongSelf.type.setImage(image, for: state)
242
                                                          }
243
 
244
                                                          strongSelf.setImageRequestReceipt(nil, for: state)
245
 
246
                                                          completion?(response)
247
                                                      })
248
 
249
        setImageRequestReceipt(requestReceipt, for: state)
250
    }
251
 
252
    /// Cancels the active download request for the image, if one exists.
253
    public func cancelImageRequest(for state: ControlState) {
254
        guard let receipt = imageRequestReceipt(for: state) else { return }
255
 
256
        let imageDownloader = self.imageDownloader ?? UIButton.af.sharedImageDownloader
257
        imageDownloader.cancelRequest(with: receipt)
258
 
259
        setImageRequestReceipt(nil, for: state)
260
    }
261
 
262
    // MARK: - Background Image Downloads
263
 
264
    /// Asynchronously downloads an image from the specified URL and sets it once the request is finished.
265
    ///
266
    /// If the image is cached locally, the image is set immediately. Otherwise the specified placeholder image will be
267
    /// set immediately, and then the remote image will be set once the image request is finished.
268
    ///
269
    /// - parameter state:            The control state of the button to set the image on.
270
    /// - parameter url:              The URL used for the image request.
271
    /// - parameter cacheKey:         An optional key used to identify the image in the cache. Defaults to `nil`.
272
    /// - parameter placeholderImage: The image to be set initially until the image request finished. If `nil`, the
273
    ///                               background image will not change its image until the image request finishes.
274
    ///                               Defaults to `nil`.
275
    /// - parameter serializer:       Image response serializer used to convert the image data to `UIImage`. Defaults
276
    ///                               to `nil` which will fall back to the instance `imageResponseSerializer` set on
277
    ///                               the `ImageDownloader`.
278
    /// - parameter filter:           The image filter applied to the image after the image request is finished.
279
    ///                               Defaults to `nil`.
280
    /// - parameter progress:         The closure to be executed periodically during the lifecycle of the request.
281
    ///                               Defaults to `nil`.
282
    /// - parameter progressQueue:    The dispatch queue to call the progress closure on. Defaults to the main queue.
283
    /// - parameter completion:       A closure to be executed when the image request finishes. The closure takes a
284
    ///                               single response value containing either the image or the error that occurred. If
285
    ///                               the image was returned from the image cache, the response will be `nil`. Defaults
286
    ///                               to `nil`.
287
    public func setBackgroundImage(for state: ControlState,
288
                                   url: URL,
289
                                   cacheKey: String? = nil,
290
                                   placeholderImage: UIImage? = nil,
291
                                   serializer: ImageResponseSerializer? = nil,
292
                                   filter: ImageFilter? = nil,
293
                                   progress: ImageDownloader.ProgressHandler? = nil,
294
                                   progressQueue: DispatchQueue = DispatchQueue.main,
295
                                   completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
296
        setBackgroundImage(for: state,
297
                           urlRequest: urlRequest(with: url),
298
                           cacheKey: cacheKey,
299
                           placeholderImage: placeholderImage,
300
                           serializer: serializer,
301
                           filter: filter,
302
                           progress: progress,
303
                           progressQueue: progressQueue,
304
                           completion: completion)
305
    }
306
 
307
    /// Asynchronously downloads an image from the specified URL request and sets it once the request is finished.
308
    ///
309
    /// If the image is cached locally, the image is set immediately. Otherwise the specified placeholder image will be
310
    /// set immediately, and then the remote image will be set once the image request is finished.
311
    ///
312
    /// - parameter state:            The control state of the button to set the image on.
313
    /// - parameter urlRequest:       The URL request.
314
    /// - parameter cacheKey:         An optional key used to identify the image in the cache. Defaults to `nil`.
315
    /// - parameter placeholderImage: The image to be set initially until the image request finished. If `nil`, the
316
    ///                               background image will not change its image until the image request finishes.
317
    ///                               Defaults to `nil`.
318
    /// - parameter serializer:       Image response serializer used to convert the image data to `UIImage`. Defaults
319
    ///                               to `nil` which will fall back to the instance `imageResponseSerializer` set on
320
    ///                               the `ImageDownloader`.
321
    /// - parameter filter:           The image filter applied to the image after the image request is finished.
322
    ///                               Defaults to `nil`.
323
    /// - parameter progress:         The closure to be executed periodically during the lifecycle of the request.
324
    ///                               Defaults to `nil`.
325
    /// - parameter progressQueue:    The dispatch queue to call the progress closure on. Defaults to the main queue.
326
    /// - parameter completion:       A closure to be executed when the image request finishes. The closure takes a
327
    ///                               single response value containing either the image or the error that occurred. If
328
    ///                               the image was returned from the image cache, the response will be `nil`. Defaults
329
    ///                               to `nil`.
330
    public func setBackgroundImage(for state: ControlState,
331
                                   urlRequest: URLRequestConvertible,
332
                                   cacheKey: String? = nil,
333
                                   placeholderImage: UIImage? = nil,
334
                                   serializer: ImageResponseSerializer? = nil,
335
                                   filter: ImageFilter? = nil,
336
                                   progress: ImageDownloader.ProgressHandler? = nil,
337
                                   progressQueue: DispatchQueue = DispatchQueue.main,
338
                                   completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
339
        guard !isImageURLRequest(urlRequest, equalToActiveRequestURLForState: state) else {
340
            let response = AFIDataResponse<UIImage>(request: nil,
341
                                                    response: nil,
342
                                                    data: nil,
343
                                                    metrics: nil,
344
                                                    serializationDuration: 0.0,
345
                                                    result: .failure(AFIError.requestCancelled))
346
 
347
            completion?(response)
348
 
349
            return
350
        }
351
 
352
        cancelBackgroundImageRequest(for: state)
353
 
354
        let imageDownloader = self.imageDownloader ?? UIButton.af.sharedImageDownloader
355
        let imageCache = imageDownloader.imageCache
356
 
357
        // Use the image from the image cache if it exists
358
        if let request = urlRequest.urlRequest {
359
            let cachedImage: Image?
360
 
361
            if let cacheKey = cacheKey {
362
                cachedImage = imageCache?.image(withIdentifier: cacheKey)
363
            } else {
364
                cachedImage = imageCache?.image(for: request, withIdentifier: filter?.identifier)
365
            }
366
 
367
            if let image = cachedImage {
368
                let response = AFIDataResponse<UIImage>(request: urlRequest.urlRequest,
369
                                                        response: nil,
370
                                                        data: nil,
371
                                                        metrics: nil,
372
                                                        serializationDuration: 0.0,
373
                                                        result: .success(image))
374
 
375
                type.setBackgroundImage(image, for: state)
376
                completion?(response)
377
 
378
                return
379
            }
380
        }
381
 
382
        // Set the placeholder since we're going to have to download
383
        if let placeholderImage = placeholderImage { type.setBackgroundImage(placeholderImage, for: state) }
384
 
385
        // Generate a unique download id to check whether the active request has changed while downloading
386
        let downloadID = UUID().uuidString
387
 
388
        // Weakify the button to allow it to go out-of-memory while download is running if deallocated
389
        weak var button = type
390
 
391
        // Download the image, then set the image for the control state
392
        let requestReceipt = imageDownloader.download(urlRequest,
393
                                                      cacheKey: cacheKey,
394
                                                      receiptID: downloadID,
395
                                                      serializer: serializer,
396
                                                      filter: filter,
397
                                                      progress: progress,
398
                                                      progressQueue: progressQueue,
399
                                                      completion: { response in
400
                                                          guard
401
                                                              let strongSelf = button?.af,
402
                                                              strongSelf.isBackgroundImageURLRequest(response.request, equalToActiveRequestURLForState: state) &&
403
                                                              strongSelf.backgroundImageRequestReceipt(for: state)?.receiptID == downloadID
404
                                                          else {
405
                                                              completion?(response)
406
                                                              return
407
                                                          }
408
 
409
                                                          if case let .success(image) = response.result {
410
                                                              strongSelf.type.setBackgroundImage(image, for: state)
411
                                                          }
412
 
413
                                                          strongSelf.setBackgroundImageRequestReceipt(nil, for: state)
414
 
415
                                                          completion?(response)
416
                                                      })
417
 
418
        setBackgroundImageRequestReceipt(requestReceipt, for: state)
419
    }
420
 
421
    /// Cancels the active download request for the background image, if one exists.
422
    public func cancelBackgroundImageRequest(for state: ControlState) {
423
        guard let receipt = backgroundImageRequestReceipt(for: state) else { return }
424
 
425
        let imageDownloader = self.imageDownloader ?? UIButton.af.sharedImageDownloader
426
        imageDownloader.cancelRequest(with: receipt)
427
 
428
        setBackgroundImageRequestReceipt(nil, for: state)
429
    }
430
 
431
    // MARK: - Internal - Image Request Receipts
432
 
433
    func imageRequestReceipt(for state: ControlState) -> RequestReceipt? {
434
        guard let receipt = imageRequestReceipts[state.rawValue] else { return nil }
435
        return receipt
436
    }
437
 
438
    func setImageRequestReceipt(_ receipt: RequestReceipt?, for state: ControlState) {
439
        var receipts = imageRequestReceipts
440
        receipts[state.rawValue] = receipt
441
 
442
        imageRequestReceipts = receipts
443
    }
444
 
445
    // MARK: - Internal - Background Image Request Receipts
446
 
447
    func backgroundImageRequestReceipt(for state: ControlState) -> RequestReceipt? {
448
        guard let receipt = backgroundImageRequestReceipts[state.rawValue] else { return nil }
449
        return receipt
450
    }
451
 
452
    func setBackgroundImageRequestReceipt(_ receipt: RequestReceipt?, for state: ControlState) {
453
        var receipts = backgroundImageRequestReceipts
454
        receipts[state.rawValue] = receipt
455
 
456
        backgroundImageRequestReceipts = receipts
457
    }
458
 
459
    // MARK: - Private - URL Request Helpers
460
 
461
    private func isImageURLRequest(_ urlRequest: URLRequestConvertible?,
462
                                   equalToActiveRequestURLForState state: ControlState)
463
        -> Bool {
464
        if
465
            let currentURL = imageRequestReceipt(for: state)?.request.task?.originalRequest?.url,
466
            let requestURL = urlRequest?.urlRequest?.url,
467
            currentURL == requestURL {
468
            return true
469
        }
470
 
471
        return false
472
    }
473
 
474
    private func isBackgroundImageURLRequest(_ urlRequest: URLRequestConvertible?,
475
                                             equalToActiveRequestURLForState state: ControlState)
476
        -> Bool {
477
        if
478
            let currentRequestURL = backgroundImageRequestReceipt(for: state)?.request.task?.originalRequest?.url,
479
            let requestURL = urlRequest?.urlRequest?.url,
480
            currentRequestURL == requestURL {
481
            return true
482
        }
483
 
484
        return false
485
    }
486
 
487
    private func urlRequest(with url: URL) -> URLRequest {
488
        var urlRequest = URLRequest(url: url)
489
 
490
        for mimeType in ImageResponseSerializer.acceptableImageContentTypes.sorted() {
491
            urlRequest.addValue(mimeType, forHTTPHeaderField: "Accept")
492
        }
493
 
494
        return urlRequest
495
    }
496
}
497
 
498
// MARK: - Deprecated
499
 
500
extension UIButton {
501
    @available(*, deprecated, message: "Replaced by `button.af.imageDownloader`")
502
    public var af_imageDownloader: ImageDownloader? {
503
        get { af.imageDownloader }
504
        set { af.imageDownloader = newValue }
505
    }
506
 
507
    @available(*, deprecated, message: "Replaced by `button.af.sharedImageDownloader`")
508
    public class var af_sharedImageDownloader: ImageDownloader {
509
        get { af.sharedImageDownloader }
510
        set { af.sharedImageDownloader = newValue }
511
    }
512
 
513
    @available(*, deprecated, message: "Replaced by `button.af.sharedImageDownloader`")
514
    public func af_setImage(for state: ControlState,
515
                            url: URL,
516
                            cacheKey: String? = nil,
517
                            placeholderImage: UIImage? = nil,
518
                            serializer: ImageResponseSerializer? = nil,
519
                            filter: ImageFilter? = nil,
520
                            progress: ImageDownloader.ProgressHandler? = nil,
521
                            progressQueue: DispatchQueue = DispatchQueue.main,
522
                            completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
523
        af.setImage(for: state,
524
                    url: url,
525
                    cacheKey: cacheKey,
526
                    placeholderImage: placeholderImage,
527
                    serializer: serializer,
528
                    filter: filter,
529
                    progress: progress,
530
                    progressQueue: progressQueue,
531
                    completion: completion)
532
    }
533
 
534
    @available(*, deprecated, message: "Replaced by `button.af.sharedImageDownloader`")
535
    public func af_setImage(for state: ControlState,
536
                            urlRequest: URLRequestConvertible,
537
                            cacheKey: String? = nil,
538
                            placeholderImage: UIImage? = nil,
539
                            serializer: ImageResponseSerializer? = nil,
540
                            filter: ImageFilter? = nil,
541
                            progress: ImageDownloader.ProgressHandler? = nil,
542
                            progressQueue: DispatchQueue = DispatchQueue.main,
543
                            completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
544
        af.setImage(for: state,
545
                    urlRequest: urlRequest,
546
                    cacheKey: cacheKey,
547
                    placeholderImage: placeholderImage,
548
                    serializer: serializer,
549
                    filter: filter,
550
                    progress: progress,
551
                    progressQueue: progressQueue,
552
                    completion: completion)
553
    }
554
 
555
    /// Cancels the active download request for the image, if one exists.
556
    public func af_cancelImageRequest(for state: ControlState) {
557
        af.cancelImageRequest(for: state)
558
    }
559
 
560
    @available(*, deprecated, message: "Replaced by `button.af.sharedImageDownloader`")
561
    public func af_setBackgroundImage(for state: ControlState,
562
                                      url: URL,
563
                                      cacheKey: String? = nil,
564
                                      placeholderImage: UIImage? = nil,
565
                                      serializer: ImageResponseSerializer? = nil,
566
                                      filter: ImageFilter? = nil,
567
                                      progress: ImageDownloader.ProgressHandler? = nil,
568
                                      progressQueue: DispatchQueue = DispatchQueue.main,
569
                                      completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
570
        af.setBackgroundImage(for: state,
571
                              url: url,
572
                              cacheKey: cacheKey,
573
                              placeholderImage: placeholderImage,
574
                              serializer: serializer,
575
                              filter: filter,
576
                              progress: progress,
577
                              progressQueue: progressQueue,
578
                              completion: completion)
579
    }
580
 
581
    @available(*, deprecated, message: "Replaced by `button.af.sharedImageDownloader`")
582
    public func af_setBackgroundImage(for state: ControlState,
583
                                      urlRequest: URLRequestConvertible,
584
                                      cacheKey: String? = nil,
585
                                      placeholderImage: UIImage? = nil,
586
                                      serializer: ImageResponseSerializer? = nil,
587
                                      filter: ImageFilter? = nil,
588
                                      progress: ImageDownloader.ProgressHandler? = nil,
589
                                      progressQueue: DispatchQueue = DispatchQueue.main,
590
                                      completion: ((AFIDataResponse<UIImage>) -> Void)? = nil) {
591
        af.setBackgroundImage(for: state,
592
                              urlRequest: urlRequest,
593
                              cacheKey: cacheKey,
594
                              placeholderImage: placeholderImage,
595
                              serializer: serializer,
596
                              filter: filter,
597
                              progress: progress,
598
                              progressQueue: progressQueue,
599
                              completion: completion)
600
    }
601
 
602
    /// Cancels the active download request for the background image, if one exists.
603
    public func af_cancelBackgroundImageRequest(for state: ControlState) {
604
        af.cancelBackgroundImageRequest(for: state)
605
    }
606
}
607
 
608
// MARK: - Private - AssociatedKeys
609
 
610
private enum AssociatedKeys {
611
    static var imageDownloader = "UIButton.af.imageDownloader"
612
    static var sharedImageDownloader = "UIButton.af.sharedImageDownloader"
613
    static var imageReceipts = "UIButton.af.imageReceipts"
614
    static var backgroundImageReceipts = "UIButton.af.backgroundImageReceipts"
615
}
616
 
617
#endif