Kingfisher е библиотека за зареждане и кеширане на изображения на iOS, macOS и watchOS, написана на чист Swift. Според официалното хранилище, библиотеката осигурява пълна поддръжка за Swift Concurrency, Combine и SwiftUI, както и автоматично кеширане на две нива. Kingfisher е известна с типобезопасно API и лесна интеграция с проекти на Swift.
Основни точки
Kingfisher — библиотека за асинхронно зареждане и кеширане на изображения на платформите на Apple, написана изцяло на Swift. Автор на библиотеката е Wei Wang (onevcat). Kingfisher предоставя набор от инструменти за зареждане на изображения от мрежата с автоматично кеширане, трансформации и поддръжка на модерни Swift технологии: async/await, Combine, Sendable.
Библиотеката има над 23 000 звезди в GitHub и се използва в приложения като Telegram, Snapchat и Dropbox. Kingfisher поддържа GIF, APNG, HEIF и всички стандартни формати на изображения. Всяка заявка връща типобезопасен Result
Архитектурата на Kingfisher е изградена върху три основни компонента: Manager (мениджър на зареждане), Cache (двустепенен кеш) и Processor (трансформации). Тези компоненти са свързани чрез протоколи, което позволява замяна на всяка част без промяна на зависимостите.
KingfisherManager — централният клас, който координира зареждането, кеширането и обработката на изображения. Той съдържа референции към ImageCache и ImageDownloader и предоставя единен метод retrieveImage, който връща готовото изображение след преминаване през всички етапи.
При извикване на retrieveImage, Manager първо проверява Memory Cache — NSCache с UIImage, където ключът се формира от URL на източника и CacheSerializer. Ако изображението бъде намерено — връща се незабавно. При липса се проверява Disk Cache — четене от файловата система с дешифриране чрез serializer. Ако кешът на диска е празен, се изпълнява мрежова заявка чрез ImageDownloader, резултатът се декодира, трансформира и записва и на двете нива на кеша.
От версия 7.0, Kingfisher напълно поддържа async/await. Методът retrieveImage е достъпен като асинхронна функция, връщаща Result директно без completion блокове. Това позволява използване на библиотеката в модерни Swift архитектури със Structured Concurrency.
Kingfisher е разделена на няколко модула, всеки от които решава своя задача. Това разделение улеснява тестването и замяната на компоненти.
KingfisherManager — фасада, която обединява зареждане, кеш и процесори. По подразбиране се използва сингълтон KingfisherManager.shared, но може да се създаде отделен екземпляр с персонализирани настройки за изолирани сценарии (например за модулни тестове).
ImageCache — двустепенен кеш с отделни настройки за памет и диск. Memory Cache няма ограничение за броя на обектите, но се изчиства от системата при недостиг на памет. Disk Cache съхранява файлове в директория с настройки за TTL (по подразбиране 7 дни), лимит на размера (по подразбиране 0 — без ограничение) и автоматично изчистване.
ImageProcessor — протокол с единствен метод process(item:options:), връщащ обработеното изображение. Вградени реализации: ResizingImageProcessor (промяна на размер), RoundCornerImageProcessor (заобляне), BlurImageProcessor (Гаусово размазване), OverlayImageProcessor (добавяне на цвят). Процесорите могат да се комбинират чрез оператора |>.
Архитектурата на кеша на Kingfisher се основава на принципа write-through: данните се записват едновременно на двете нива, а четенето започва от най-бързото ниво — паметта. Ключът на кеша е абсолютният URL на изображението след премахване на query параметрите.
| Параметър | Memory Cache | Disk Cache |
|---|---|---|
| Съхранение | NSCache (RAM) | Файлова система (SSD) |
| Формат | UIImage (декодиран) | Data (компресиран, чрез serializer) |
| Изчистване | UIApplication.didReceiveMemoryWarningNotification | TTL + превишаване на лимит |
| Сериализация | Не се изисква | CacheSerializer (по подразбиране PNG/JPEG) |
| Нишкова безопасност | Да (синхронизиран достъп) | Да (IO опашка + бариери) |
За управление на размера на Disk Cache се използва изчисляване на общия размер на файловете със сортиране по дата на последен достъп. При превишаване на лимита, файловете с най-стара дата на достъп се изтриват, докато размерът падне под 50% от лимита. TTL изчистването става при инициализация на кеша и при всяко извикване на cleanExpired.
Kingfisher предоставя няколко интерфейса за зареждане на изображения: разширение на UIImageView, отделен мениджър и SwiftUI View.
kf — namespace свойство на UIImageView, предоставящо методите setImage, cancelDownload и индикатори за зареждане. Методът setImage приема URLSource и опционални параметри Options и completionHandler.
import Kingfisher
imageView.kf.setImage(
with: URL(string: "https://example.com/image.jpg"),
placeholder: UIImage(named: "placeholder"),
options: [
.processor(RoundCornerImageProcessor(radius: .point(12))),
.transition(.fade(0.3)),
.cacheMemoryOnly
],
progressBlock: { receivedSize, totalSize in
print("Заредено \(receivedSize) / \(totalSize)")
}
)
Методът връща DownloadTask, който поддържа отмяна чрез cancel и проследяване на напредъка. Вътрешно setImage извиква KingfisherManager.shared.retrieveImage с автоматично определяне на ImageView като Target.
От Kingfisher 7.0, методът setImage е достъпен в асинхронна версия. Това позволява интегриране на зареждане на изображения в Swift Structured Concurrency без callback-ове.
func loadAvatar() async {
do {
let result = try await imageView.kf.setImage(
with: url,
options: [.processor(ResizingImageProcessor(
targetSize: CGSize(width: 100, height: 100)
))]
)
// result.image съдържа UIImage
} catch {
print("Неуспешно: \(error)")
}
}
KFImage — SwiftUI View, подобна на AsyncImage от iOS 15, но с пълна поддръжка на кеширане от Kingfisher. View автоматично използва KingfisherManager.shared, но поддържа персонализиран мениджър чрез модификатора .configure.
struct AvatarView: View {
let url: URL
var body: some View {
KFImage(url)
.placeholder { ProgressView() }
.resizable()
.fade(duration: 0.25)
.forceTransition()
.frame(width: 80, height: 80)
.cornerRadius(40)
}
}
Kingfisher предоставя вградена система от индикатори за показване на напредъка на зареждане на изображение. IndicatorType — изброяване с три варианта: .activity (UIActivityIndicatorView), .progress (UIProgressView) и .custom (персонализирана реализация на протокола Indicator). Индикаторът автоматично се показва върху ImageView по време на зареждане и се скрива след завършване.
За персонализиран индикатор трябва да се имплементира протоколът Indicator с методите startAnimatingView() и stopAnimatingView(). Това позволява използване на хибридни решения: скелет с shimmer анимация, заместващо изображение с постепенно появяване или лого с анимация на прозрачност. Kingfisher също така поддържа глобално задаване на индикатор чрез KingfisherManager.shared.defaultOptions.
На iOS платформата Kingfisher и SDWebImage са двете доминиращи библиотеки за зареждане на изображения. Изборът между тях зависи от езика на проекта, изискванията за производителност и екосистемата.
| Критерий | Kingfisher | SDWebImage |
|---|---|---|
| Език | Swift (100%) | Objective-C + Swift |
| Async/Await | Вградена поддръжка | Чрез обвивка |
| Combine | Вграден Publisher | Не |
| Sendable | Поддържа | Ограничено |
| Типова безопасност | Пълна (тип Result) | Чрез Any? |
| ImageProcessor | Composite чрез |> | Transformer чрез && |
| Размер | ~900 KB | ~1.2 MB |
| Звезди в GitHub | 23 000+ | 25 000+ |
Ключовото предимство на Kingfisher е Swift-first архитектурата: пълна поддръжка за async/await, Combine Publishers, Sendable и Result типове. SDWebImage запазва лидерството си благодарение на по-широката екосистема от плъгини (WebP, SVG, MapKit) и поддръжката на Objective-C.
Kingfisher се инсталира чрез Swift Package Manager, CocoaPods или Carthage. След инсталация е достатъчно да импортирате модула и да извикате произволен метод за зареждане — библиотеката е готова за работа без допълнителна конфигурация.
// Swift Package Manager (Package.swift)
dependencies: [
.package(
url: "https://github.com/onevcat/Kingfisher.git",
from: "7.12.0"
)
]
// CocoaPods (Podfile)
pod 'Kingfisher', '~> 7.12'
За персонализиране на глобалните настройки се използва KingfisherManager.shared. Може да се промени timeout-ът на зареждача, стратегията за кеширане и процесорите по подразбиране. По-долу е пример за конфигурация на кеш от 500 MB с TTL от 14 дни.
let cache = ImageCache(name: "custom")
cache.memoryStorage.config.totalCostLimit = 100 * 1024 * 1024
cache.diskStorage.config.sizeLimit = 500 * 1024 * 1024
cache.diskStorage.config.expiration = .days(14)
KingfisherManager.shared.cache = cache
ImageDownloader също се конфигурира чрез мениджъра: може да се зададе персонализирана URLSessionConfiguration с таймаути, хедъри и политики за кеширане. За наблюдение на напредъка е достъпен модулът KFIndicator с поддръжка на ActivityIndicator, ProgressView и персонализирани индикатори.
Често задавани въпроси
Kingfisher — библиотека за зареждане на изображения за iOS, написана на чист Swift. Използва се за асинхронно зареждане, кеширане и трансформиране на изображения от мрежата с пълна интеграция в SwiftUI, UIKit и модерни Swift технологии.
Добавете пакета https://github.com/onevcat/Kingfisher.git с версия от 7.12.0 в Xcode чрез File Add Packages. Или посочете зависимостта в Package.swift с параметър from: „7.12.0”. След инсталация импортирайте модула Kingfisher.
Kingfisher поддържа JPEG, PNG, GIF, APNG, HEIF и WebP. Всички формати се декодират чрез системни рамки (ImageIO, CoreGraphics). GIF се поддържа чрез CGImageSource с прогресивно зареждане и анимация.
Kingfisher е написан на чист Swift и напълно поддържа async/await, Combine и Sendable. Предоставя типобезопасен Result API и модулна архитектура чрез протоколи, опростявайки замяната на компоненти и тестването.
За изчистване на Memory Cache извикайте KingfisherManager.shared.cache.clearMemoryCache(). За Disk Cache използвайте clearDiskCache(). За премахване само на изтекли файлове — cleanExpiredDiskCache(). Размерът на кеша се проверява чрез cache.calculateDiskStorageSize().
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също