Swift Kingfisher使用方法

1. 调用方法解析

public func setImage(
        with resource: Resource?,
 placeholder: Placeholder? = nil
    options: KingfisherOptionsInfo? = nil,
 completionHandler: ((Result<RetrieveImageResult, KingfisherError>) -> Void)? = nil) -> DownloadTask?

参数:

  • resource:目标资源;需实现Resource协议,URL继承了Resource协议,所以可以直接用URL对象
  • placeholder:站位图;需实现Placeholder协议,可自定义一个CustomView实现Placeholder协议,将这个CustomView作为站位图显示
  • options:设置图片的一些可选项的集合;
  • completionHandler:设置图片完成的回调

使用案例:

guard let url = URL(string: "https://pic.huitu.com/res/20221125/754309_20221125075727864209_1.jpg") else {
    return
}

let originalCache = ImageCache(name: "original_Cache")
let targetCache = ImageCache(name: "target_Cache")

let processor = RoundCornerImageProcessor(cornerRadius: 50) |> BlurImageProcessor(blurRadius: 5)

let options: [KingfisherOptionsInfoItem] = [
        .transition(.flipFromBottom(0.3)),          // 从底部翻转动画
        .forceTransition,                           // 每次都要执行翻转动画
        .processor(processor),                  // 添加processor
        .onFailureImage(UIImage(named: "hot")), // 下载/找回图片失败,显示hot图片
        .targetCache(targetCache),              // 指定被处理后图片缓存
        .originalCache(originalCache),          // 指定原始图片缓存
        .cacheOriginalImage,                    // 缓存原始图片
        .waitForCache,                                                // 等待缓存结束后在执行completionBlock
        .memoryCacheExpiration(.seconds(20)),   // 设置该图片在内存缓存过期时间
        .diskCacheExpiration(.seconds(20))      // 设置该图片在磁盘缓存过期时间
]
iv.kf.setImage(with: url, options: options) { result in
    switch result {
    case .success(let img):
            // ...
    case .failure(let error):
            // ...
    }
}

2. KingfisherOptionsInfoItem - 配置选项

  • targetCache(ImageCache)

    指定kingfisher使用的cache对象,会被用来找回缓存的图片和存储下载的图片。

  • originalCache(ImageCache)

    用来存储初始图片的cache对象,会被用来找回缓存的图片和存储下载的初始图片,如果没有设置originalCache(ImageCache),则会去targetCache(ImageCache)对象中查找初始图片。

    在下载和存储图片的过程中,如果设置了cacheOriginalImage这个option,就会将初始图片缓存在originalCache中;如果在targetCache对象中没有找到经过professor处理的图片,则会去originCache中查找原始图片,如果在originalCache中找到了原始图片,则会将该图片根据professor进行处理。这样能有效防止重复下载图片。

  • downloader(ImageDownloader)

    指定用来下载图片的ImageDownloader对象

  • transition(ImageTransition)

    如果该图片是需要从网络下载的,Kingfisher会根据设置的ImageTransition枚举对象来对这个图片进行动画。如果是从缓存或者磁盘中找回的,则无动画。如果想要每次都执行动画,则需要设置.forceRefresh选项,使图片永远是下载的;或者使用.forceTransition,哪怕是从缓存中获取的图片,也会执行动画。

  • downloadPriority(Float)

    设置该图片下载的优先级,值的范围是0 - 1,如果没有设置这个选项,则默认使用URLSessionTask.defaultPriority

  • forceRefresh

    忽略本地缓存,重新下载

  • fromMemoryCacheOrRefresh

    如果设置了这个选项,Kingfisher会优先从缓存中找回图片,如果在缓存中没找到,则会直接开始重新下载,不会再去磁盘中进行查找。

    当我们的图片资源发生变化,但是图片的url并没有发生变化时,可使用该选项,能有效防止多次重复下载。

  • cacheMemoryOnly

    只将图片存储在缓存中

  • waitForCache

    Kingfisher只会在缓存操作结束后再执行completion回调

  • onlyFromCache

    只会在缓存中找回图片,如果没找到,不会通过网络下载,而是直接报错:KingfisherError.cacheError(reason: .imageNotExisting(key: source.cacheKey))

  • backgroundDecode

    在使用图片前,会启用子线程对下载的图片进行解析,并且通过离屏渲染获取像素信息。这会使得展示的速度更快,但是要消耗更多的时间来做使用前的准备

  • callbackQueue(CallbackQueue)

    从缓存中找回图片后的回调,将会在该queue中进行操作,如果没有设置,则默认使用.mainCurrentOrAsync

    这个queue不会影响UI相关的扩展方法的回调所在的队列,UI类的扩展方法的回调都是在主队列中进行的。

  • scaleFactor(CGFloat)

    在将找回的data转换成图片时,使用这个关联值来设置图片的scale;比如加载2x和3x图片时,可以使用这个option来设置,如果不设置这个option,Kingfisher会按照scale为1.0去讲data转为image

  • preloadAllAnimationData

    整个的动图data是否被预加载。默认是不预加载整个的动图数据的,只是按需加载下一帧;如果设置为true,则会将整个动图的data加载并解码到内存中;

    这个option主要用于内部的向后兼容。开发时,不能直接设置这个option,而是应该选择imageView的相关类来控制data的加载。在Kingfisher中,有两个类用来展示动图,AnimatedImageViewUIImageViewAnimatedImageView不会预加载所有动图data,在加载动图的过程中,它消耗更少的内存,但会消耗更多的CPU。UIImageView会立即加载整个动图的data并解码存储到内存中,所以会消耗更多的内存,但只对所有的图片帧解码一次。

  • requestModifier(AsyncImageDownloadRequestModifier)

    可以通过关联值AsyncImageDownloadRequestModifier对象来设置request,这是最后一次修改下载图片request的机会。比如我们可以在这里为header添加auth token,url映射等。

  • redirectHandler(ImageDownloadRedirectHandler)

    关联值ImageDownloadRedirectHandler用来在重定向之前去设置request,比如:我们可以在这里为header添加auth token,url映射等。

  • processor(ImageProcessor)

    在图片下载完成后,关联值ImageProcessor会被用来将下载的data处理为image,并添加一些效果。如果下载器关联了某个cache对象(通过KingfisherManager或者UIImageView的扩展方法触发的下载都有cache对象),转换后的image也会被缓存下来。可联系上面的targetCache(ImageCache)originCache(ImageCache)两个option。

  • cacheSerializer(CacheSerializer)

    在关联值CacheSerializer会被用来将data处理为Image,以便从磁盘缓存中找回或从缓存到磁盘缓存中

  • imageModifier(ImageModifier)

    关联值ImageModifier用来在使用图片之前修改图片的。如果图片是从下载器中获取的,关联值modifier会在ImageProcessor之后被立即调用;如果是从缓存中找回的,关联值modifier将会在CacheSerializer之后被调用。

    当你需要改变图片,但是又不希望这些改变被和图片一起缓存起来,则可以通过这个option来设置,比如renderingModel(原色显示、根据tintColor显示)或者alignmentInsets(剔除装饰如阴影、徽章,圈定核心区域,自动布局也是根据核心区域去进行的)

  • keepCurrentImageWhileLoading

    在设置其它图片的过程中(如下载),保留当前图片。设置了这个属性之后,站位图会被忽略。

  • onlyLoadFirstFrame

    在加载动图时,只加载第一帧。因为加载动图时比较耗费内存的,所以可以加载第一帧作为预览图片。

    如果不是加载动图,这个option设置了也会被忽略。

  • cacheOriginalImage

    初始图片只会被缓存到磁盘存储。

    在下载时,如果设置了ImageProcessor并且该processor被使用到了,Kingfisher会缓存初始图片和经过处理的最终图片,因此,当其他processor对该图片进行处理时,就不需要从网络下载了。可以结合originalCache option来指定初始图片资源的缓存。

  • onFailureImage(KFCrossPlatformImage?)

    关联属性是个image,当下载或者从缓存中找回图片失败时,会使用这个image填充到ImageView中。

    适用于不想设置站位图,但是加载图片失败了,又想展示一个设定的图片的情况。

  • alsoPrefetchToMemory

    如果使用了ImagePrefetcher,预加载系统会主动将图片加载到内存中。预加载时如果图片已经被存放在磁盘中,从磁盘获取的图片也要缓存到内存中

  • loadDiskFileSynchronously

    同步加载磁盘图片文件。

    原本地盘加载图片在自己的异步队列中进行,但是如果imageView已经有图片了,再从磁盘读取image并设置给imageView,会导致闪烁。设置这个option,通常会让所有的加载在UI线程中进行,能防止产生闪烁,但会消耗性能。

  • diskStoreWriteOptions(Data.WritingOptions)

    在将data写入磁盘存储时,关联对象用来设置写入选项

  • memoryCacheExpiration(StorageExpiration)

    设置内存缓存的过期时间

  • memoryCacheAccessExtendingExpiration(ExpirationExtending)

    从内存读取图片时,设置延长过期时间的策略

    1. none:保持原来的过期时间

    2. `cacheTime:刷新过期时间,如原来是缓存成功3天后过期,本次访问过后,从当前时间开始,3天后过期

    3. expirationTime(_ expiration: StorageExpiration) :设置过期时间为指定的时间,如10秒后

  • diskCacheExpiration(StorageExpiration)

    设置磁盘缓存的过期时间

  • diskCacheAccessExtendingExpiration(ExpirationExtending)

    同上面的memoryCacheAccessExtendingExpiration(ExpirationExtending)

  • processingQueue(CallbackQueue)

    指定处理图片的队列。

    默认情况下,Kingfisher使用预定义的串行队列来处理图片。比如:使用.mainCurrentOrAsync来处理图片,能防止设置闪烁,但是如果处理图片耗时较长,会阻塞主线程UI。

  • progressiveJPEG(ImageProgressive)

    支持渐进式图片,关联值为针对渐进式图片的处理。

  • alternativeSources([Source])

    加载失败时,提供可替换的数据源。

    当初始请求失败,则会根据关联值[Source]开始新的加载请求。如果某一个请求成功,则不会继续请求后面的Source;如果所有的备用Source都请求失败了,则会抛出错误

  • retryStrategy(RetryStrategy)

    设置重试策略。

    当通过KingfisherManager找回图片时,如果发生了错误,会使用关联值进行重试。UIImageView和UIButton通过kf调用的的扩展方法都是通过KingfisherManager进行的,所以重试策略在这两个情况下可以生效。但是重试策略不支持ImageDownloader或者ImageCache

  • lowDataMode(Source?)

    设置低数据模式。

    当用户打开了低数据模式并且初始请求报错:NSURLErrorNetworkUnavailableReason.constrained,此时如果设置了这个option,关联值Source将会被用于进行低数据模式的请求,此外,可以让服务端提供低像素的图片来作为低数据模式获取的资源。

3. ImageProcessor - 图片处理器

通过processor(ImageProcessor)设置ImageProcessor会对下载的原始图片进行处理并被缓存。

// 圆角
// let processor = RoundCornerImageProcessor(cornerRadius: 20)

// 降低采样率,会使图片变模糊
// let processor = DownsamplingImageProcessor(size: CGSize(width: 50, height: 50))

// 裁剪
// let processor = CroppingImageProcessor(size: CGSize(width: 100, height: 100), anchor: CGPoint(x: 0.5, y: 0.5))

// 毛玻璃
// let processor = BlurImageProcessor(blurRadius: 10)

// 在图片表面覆盖一层颜色
// let processor = OverlayImageProcessor(overlay: .white, fraction: 0.7)

// 用一种颜色进行着色,会覆盖原图
// let processor = TintImageProcessor(tint: .blue)

 // 饱和度、对比度等调整
// let processor = ColorControlsProcessor(brightness: 1.0, contrast: 0.7, saturation: 1.1, inputEV: 0.7)

// 黑白图
// let processor = BlackWhiteProcessor()

// 混合颜色
// let processor = BlendImageProcessor(blendMode: .colorBurn, alpha: 0.9, backgroundColor: .cyan)

// 重设图片大小
// let processor = ResizingImageProcessor(referenceSize: CGSize(width: 10, height: 10))

设置方法:

let processor = RoundCornerImageProcessor(cornerRadius: 20)
let options = [.processor(processor)]
iv.kf.setImage(with: url, options: options) { result in
        // ...                                             
}

多个processor结合使用

let processor = RoundCornerImageProcessor(cornerRadius: 20) |> BlurImageProcessor(blurRadius: 10)
let options = [.processor(processor)]
iv.kf.setImage(with: url, options: options) { result in
        // ...                                             
}

4. Cache - 缓存

Kingfisher使用ImageCache类来控制缓存,它采用混合缓存的模式,包含内存缓存和磁盘缓存。

  1. 指定图片的cacheKey

    let resource = ImageResource(downloadURL: url, cacheKey: "my_cache_key")
    imageView.kf.setImage(with: resource)
    
  2. 检查图片是否被缓存

    let cached = ImageCache.default.isCached(forKey: cacheKey)
    
  3. 检查图片被缓存的位置

    let cacheType = cache.imageCachedType(forKey: cacheKey)
    // .memory, .disk, .none
    
  4. 从缓存中找回图片

    cache.retrieveImage(forKey: "cacheKey") { result in
        switch result {
        case .success(let value):
            print(value.cacheType)
    
            // If the `cacheType is `.none`, `image` will be `nil`.
            print(value.image)
    
        case .failure(let error):
            print(error)
        }
    }
    
  1. 在下载或者从缓存找回图片时,使用processor对图片进行了一些处理,则经过处理的图片会被缓存下来,所以在获取该图片时,不仅需要图片的cacheKey,还需要processoridentifier,这样才能从缓存中找到经过处理的图片。

    let processor = RoundCornerImageProcessor(cornerRadius: 20)
    imageView.kf.setImage(with: url, options: [.processor(processor)])
    

    判断是否缓存了经过处理的图片

    cache.isCached(forKey: cacheKey, processorIdentifier: processor.identifier)
    

    找回经过处理的图片

    cache.retrieveImage(forKey: cacheKey, options: KingfisherParsedOptionsInfo([processor])) { result in
         switch result {
        case .success(let value):
            print(value.cacheType)
    
            // If the `cacheType is `.none`, `image` will be `nil`.
            print(value.image)
    
        case .failure(let error):
            print(error)
        }
    }
    
  2. 设置cache的内存大小

    设置内存缓存大小

    // 设置缓存内存最大为 300 MB.
    cache.memoryStorage.config.totalCostLimit = 300 * 1024 * 1024
    
    // 最多缓存150张图片 
    cache.memoryStorage.config.countLimit = 150
    

    设置磁盘缓存大小

    // 设置磁盘缓存内存最大 1 GB.
    cache.diskStorage.config.sizeLimit =  = 1000 * 1024 * 1024
    
  3. 设置缓存过期时间

    设置cache对象下的所有内存缓存过期时间

    // 内存缓存10分钟后过期
    cache.memoryStorage.config.expiration = .seconds(600)
    
    // 磁盘缓存永不过期
    cache.diskStorage.config.expiration = .never
    

    针对某张图片设置过期时间,内存缓存和磁盘缓存都可设置,还可以在访问缓存图片时设置memoryCacheAccessExtendingExpiration option来延长缓存时间

    imageView.kf.setImage(with: url, options: [.memoryCacheExpiration(.never)])
    
    // 在获取图片时延长缓存时间
    cache.retrieveImageInDiskCache(forKey: url.cacheKey, options: [.diskCacheAccessExtendingExpiration(.expirationTime(.seconds(100)))]) { result in
         // ...                    
    }
    
  4. 清理缓存

    1. 内存缓存每隔2分钟会清理一下缓存,如果想更频繁地清理缓存,可设置

      cache.memoryStorage.config.cleanInterval = 30
      
    2. 清理某一张图片

      cache.default.removeImage(forKey: cacheKey)
      

      或者调用更强大的方法

      cache.removeImage(
          forKey: cacheKey,
          processorIdentifier: processor.identifier,
          fromMemory: false,
          fromDisk: true)
      {
          print("Removed!")
      }
      
    3. 清理所有缓存

      cache.clearMemoryCache()
      cache.clearDiskCache { print("Done") }
      
    4. 清理过期缓存

      cache.cleanExpiredMemoryCache()
      cache.cleanExpiredDiskCache { print("Done") }
      
  5. 获取已用磁盘缓存大小

    ImageCache.default.calculateDiskStorageSize { result in
        switch result {
        case .success(let size):
            print("Disk cache size: \(Double(size) / 1024 / 1024) MB")
        case .failure(let error):
            print(error)
        }
    }
    
  6. 自定义cache

    let originalCache = ImageCache(name: "original_Cache")
    let targetCache = ImageCache(name: "target_Cache")
    

    结合option使用

    let options: [KingfisherOptionsInfoItem] = [
                        .cacheOriginalImage,                                        // 存储原始图片
                .originalCache(originalCache),                  // 设置存储原始图片的cache
                          .targetCache(targetCache),                            // 设置目标cache,上面设置了originCache,这里会存放处理后的图片
                .waitForCache,                                                  // 等待cache完成再执行completion closure
                .memoryCacheExpiration(.seconds(200)),  // 设置内存缓存过期时间
                .diskCacheExpiration(.seconds(400))         // 设置磁盘缓存过期时间
    ]
    

    上面的options实现了以下功能:

    • 存储原始图片并设置原始图片存储的cache对象为originCache,此时原始图片是存储在磁盘缓存中的;
    • 经过processor处理的图片是由targetCache负责存储的,可以结合processor.identifier在targetCache中找回图片
    • 设置了图片在内存和磁盘中缓存的过期时间

5. Downloader - 下载器

  1. 一般情况下,建议使用UIImageView等的扩展方法或者KingfisherManager来加载图片,因为它们会将图片缓存到本地,防止重复下载;如果我们只是下载图片,不需要缓存图片,则可以这样:

    let downloader = ImageDownloader.default
    downloader.downloadImage(with: url) { result in
        switch result {
        case .success(let value):
            print(value.image)
        case .failure(let error):
            print(error)
        }
    }
    
  2. 取消下载

    如果在取消下载前,下载已经完成,则不会有任何影响。

    let task = downloader.downloadImage(with: url) { result in
        // ...
        case .failure(let error):
            print(error.isTaskCancelled) // true
        }
    
    }
    
    // 在下载完成前,取消下载
    task?.cancel()
    

    可以通过UI类的扩展方法来取消下载

    let task = imageView.kf.set(with: url)
    task?.cancel()
    

    还可以通过调用cancelDownloadTask方法来取消下载

    let task1 = imageView.kf.set(with: url1)
    let task2 = imageView.kf.set(with: url2)
    
    imageView.kf.cancelDownloadTask()
    

    task2会被取消,但是task1还是会执行。

    但是task1下载的图片不会被设置到ImageView上,因为ImageView期望的是通过url2返回的图片

  3. 自定义对服务端challenge的回应

    ImageDownloader有一个默认的.performDefaultHandling来应对服务端的挑战,我们也可以自定义对服务端挑战的回应

    // In ViewController
    ImageDownloader.default.authenticationChallengeResponder = self
    
    extension ViewController: AuthenticationChallengeResponsable {
    
        var disposition: URLSession.AuthChallengeDisposition { /* */ }
        let credential: URLCredential? { /* */ }
    
        func downloader(
            _ downloader: ImageDownloader,
            didReceive challenge: URLAuthenticationChallenge,
            completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
        {
            // Provide your `AuthChallengeDisposition` and `URLCredential`
            completionHandler(disposition, credential)
        }
    
        func downloader(
            _ downloader: ImageDownloader,
            task: URLSessionTask,
            didReceive challenge: URLAuthenticationChallenge,
            completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
        {
            // Provide your `AuthChallengeDisposition` and `URLCredential`
            completionHandler(disposition, credential)
        }
    }
    
  4. 设置下载超时时间

    // 设置超时时间为1分钟
    downloader.downloadTimeout = 60
    
  5. 对某一个特定的下载设置超时时间

    let modifier = AnyModifier { request in
        var r = request
        r.timeoutInterval = 60
        return r
    }
    downloader.downloadImage(with: url, options: [.requestModifier(modifier)])
    

6. Serializer - 序列化

序列化指的就是将Image转换成data以便进行缓存,或将data转换成Image以便展示在页面上。

默认情况下使用的是DefaultCacheSerializer,它支持PNG,JPEG和GIF。如果我们想支持WEBP,可以通过实现CacheSerializer协议来自定义一个Serializer:

struct WebpCacheSerializer: CacheSerializer {
    func data(with image: Image, original: Data?) -> Data? {
        return WebpFramework.webpData(of: image)
    }
    
    func image(with data: Data, options: KingfisherParsedOptionsInfo?) -> Image? {
        return WebpFramework.createImage(from: webpData)
    }
}

// 使用
let serializer = WebpCacheSerializer()
let url = URL(string: "https://yourdomain.com/example.webp")
imageView.kf.setImage(with: url, options: [.cacheSerializer(serializer)])

7. Prefetch - 预获取图片

如果我们确定接下来将要使用一些图片 ,那么我们可以使用预获取功能

let urls = ["https://example.com/image1.jpg", "https://example.com/image2.jpg"]
           .map { URL(string: $0)! }
let prefetcher = ImagePrefetcher(urls: urls) {
    skippedResources, failedResources, completedResources in
    print("These resources are prefetched: \(completedResources)")
}
prefetcher.start()

// 使用方法
imageView.kf.setImage(with: urls[0])
anotherImageView.kf.setImage(with: urls[1])

可以结合iOS10以后提供的UICollectionViewDataSourcePrefetchingUITableViewDataSourcePrefetching来使用:

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView?.prefetchDataSource = self
}

extension ViewController: UICollectionViewDataSourcePrefetching {
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        let urls = indexPaths.flatMap { URL(string: $0.urlString) }
        ImagePrefetcher(urls: urls).start()
    }
}

8. ImageDataProvider - 以其它形式加载图片

Kingfisher还支持从本地data获取图片,并结合processor来对图片进行加工处理。

  1. 从本地url获取图片

    let url = URL(fileURLWithPath: path)
    let provider = LocalFileImageDataProvider(fileURL: url)
    // 结合processor
    let processor = RoundCornerImageProcessor(cornerRadius: 20)
    imageView.kf.setImage(with: provider, options: [.processor(processor)])  
    
  2. 从base64获取图片

    let provider = Base64ImageDataProvider(base64String: "\/9j\/4AAQSkZJRgABAQA...", cacheKey: "some-cache-key")
    imageView.kf.setImage(with: provider)
    
  3. Video URLAVAsset的指定时间生成一张图片

    let provider = AVAssetImageDataProvider(
        assetURL: URL(string: "https://example.com/your_video.mp4")!,
        seconds: 15.0
    )
    
  4. 自定义ImageDataProvider

    遵守ImageDataProvider协议需要实现cacheKeydata(handler:)方法,data(handler:)方法的参数handler是一个闭包,闭包的参数是Result类型,所以,我们需要将经过处理的最终image data传递给Result。

    struct UserNameLetterIconImageProvider: ImageDataProvider {
        var cacheKey: String { return letter }
        let letter: String
        
        init(userNameFirstLetter: String) {
            self.letter = userNameFirstLetter
        }
        
        func data(handler: @escaping (Result<Data, Error>) -> Void) {
            
            // You can ignore these detail below.
            // It generates some data for an image with `letter` being rendered in the center.
    
            let letter = self.letter as NSString
            let rect = CGRect(x: 0, y: 0, width: 250, height: 250)
            let renderer = UIGraphicsImageRenderer(size: rect.size)
            let data = renderer.pngData { context in
                UIColor.black.setFill()
                context.fill(rect)
                
                let attributes = [
                    NSAttributedString.Key.foregroundColor: UIColor.white,
                                          .font: UIFont.systemFont(ofSize: 200)
                ]
                
                let textSize = letter.size(withAttributes: attributes)
                let textRect = CGRect(
                    x: (rect.width - textSize.width) / 2,
                    y: (rect.height - textSize.height) / 2,
                    width: textSize.width,
                    height: textSize.height)
                letter.draw(in: textRect, withAttributes: attributes)
            }
    
            // Provide the image data in `handler`.
            handler(.success(data))
        }
    }
    
    // Set image for user "John"
    let provider = UserNameLetterIconImageProvider(userNameFirstLetter: "J")
    imageView.kf.setImage(with: provider)
    

9. Indicator - 加载指示器

  1. 使用gif作为指示器

    let path = Bundle.main.path(forResource: "loader", ofType: "gif")!
    let data = try! Data(contentsOf: URL(fileURLWithPath: path))
    
    imageView.kf.indicatorType = .image(imageData: data)
    imageView.kf.setImage(with: url)
    
  2. 自定义的Indicator

    struct MyIndicator: Indicator {
        let view: UIView = UIView()
        
        func startAnimatingView() { view.isHidden = false }
        func stopAnimatingView() { view.isHidden = true }
        
        init() {
            view.backgroundColor = .red
        }
    }
    
    // 调用
    let i = MyIndicator()
    imageView.kf.indicatorType = .custom(indicator: i)
    
  3. 自定义Indicator结合progressBlock使用

    imageView.kf.setImage(with: url, progressBlock: {
        receivedSize, totalSize in
        let percentage = (Float(receivedSize) / Float(totalSize)) * 100.0
        print("downloading progress: \(percentage)%")
        myIndicator.percentage = percentage
    })
    

    注意:只有当服务端返回的response的header中包含Content-Length时,progressBlock才会执行。

10. Retry - 重试

// 最多重试5次,每次间隔3秒
let retry = DelayRetryStrategy(maxRetryCount: 5, retryInterval: .seconds(3))
// 结合option使用
imageView.kf.setImage(with: url, options: [.retryStrategy(retry)])

.second(3)DelayRetryStrategy.Interval的一个枚举项,还可以选择accumulated(3),这样重试的触发间隔时间就是3, 6, 9, 12, ...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容