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, ...

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容