- Published on
SwiftUI ilovasida rasmlarni saqlash va keshlash (cache)
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Cache (kesh) nima va nima uchun kerak
Cache — internetdan yuklab olingan ma'lumotlarni vaqtincha saqlash joyi.
| Saqlash turi | Qachon ishlatiladi |
|---|---|
| FileManager | Foydalanuvchi har doim qayta keladigan muhim ma'lumotlar (doimiy) |
| Cache | Joriy sessiya davomida qayta kerak bo'lishi mumkin, ammo har safar yuklamaslik kerak bo'lgan ma'lumotlar (vaqtinchalik) |
| Hech qanday saqlash | Faqat bir marta ko'riladigan ma'lumotlar |
Amaliy misol
Foydalanuvchi biror profil sahifasini ochadi → profil rasmi yuklanadi → boshqa sahifaga o'tadi → yana shu profil sahifasiga qaytadi.
- Cache yo'q bo'lsa: rasmni internetdan qayta yuklash kerak
- Cache bor bo'lsa: rasm allaqachon keshda — darhol ko'rsatiladi
Ilova yopilganda kesh tozalanadi — fayllar manager-dagi kabi doimiy emas.
CacheManager — NSCache bilan singleton class
class CacheManager {
static let instance = CacheManager()
private init() { } // Singleton — boshqa joydan new CacheManager() qilib bo'lmaydi
var imageCache: NSCache<NSString, UIImage> = {
let cache = NSCache<NSString, UIImage>()
cache.countLimit = 100 // Maksimal saqlash soni
cache.totalCostLimit = 1024 * 1024 * 100 // Maksimal hajm (~100 MB)
return cache
}()
}
NSCache tushuntirish
NSCache<NSString, UIImage>— kalitNSString, qiymatUIImageStringo'rnigaNSString—NSCacheObjective-C-da yozilgan, SwiftString-ni to'g'ridan-to'g'ri qabul qilmaydiStringniNSString-ga o'girish:name as NSString- Swift kompilyatori bu ikkalasini bir-biriga
asorqali bemalol o'girishga ruxsat beradi
countLimit va totalCostLimit
cache.countLimit = 100
// Keshda 100 tadan ko'p element bo'lmaydi
// 101-element qo'shilganda, eski elementlar avtomatik o'chiriladi
cache.totalCostLimit = 1024 * 1024 * 100
// Keshning umumiy hajmi ~100 MB dan oshmasin
// Oshib ketsa, eski elementlar chiqarib yuboriladi
Kesh xotirada (RAM) saqlanadi — shuning uchun hajmni nazorat qilish muhim. Haddan oshib ketsa — ilova sekinlashishi yoki crash bo'lishi mumkin.
private init — to'g'ri singleton
// NOTO'G'RI: hech narsa yangi instance yaratishni to'sqinlik qilmaydi
static let instance = CacheManager()
// TO'G'RI: private init bilan faqat class ichidan init qilish mumkin
static let instance = CacheManager()
private init() { }
private init — singleton pattern-ining to'liq versiyasi. Buni har qanday singleton-ga qo'shish tavsiya etiladi.
Keshga qo'shish — add(image:name:)
@discardableResult
func add(image: UIImage, name: String) -> String {
imageCache.setObject(image, forKey: name as NSString)
return "Added to cache"
}
setObject(_:forKey:)— keshga element qo'shish- Agar shu kalit bilan element allaqachon bo'lsa — ustiga yoziladi
Keshdan olish — get(name:)
func get(name: String) -> UIImage? {
return imageCache.object(forKey: name as NSString)
}
object(forKey:)— keshdan element olish- Agar topilmasa —
nilqaytaradi
Keshdan o'chirish — remove(name:)
@discardableResult
func remove(name: String) -> String {
imageCache.removeObject(forKey: name as NSString)
return "Removed from cache"
}
CacheViewModel
class CacheViewModel: ObservableObject {
let manager = CacheManager.instance
let imageName: String = "steve_jobs"
@Published var startingImage: UIImage? = nil
@Published var cachedImage: UIImage? = nil
@Published var infoMessage: String = ""
init() {
getImageFromAssetsFolder()
}
func getImageFromAssetsFolder() {
startingImage = UIImage(named: imageName)
}
func saveToCache() {
guard let image = startingImage else { return }
infoMessage = manager.add(image: image, name: imageName)
}
func removeFromCache() {
infoMessage = manager.remove(name: imageName)
}
func getFromCache() {
if let returnedImage = manager.get(name: imageName) {
cachedImage = returnedImage
infoMessage = "Got image from cache"
} else {
infoMessage = "Image not found in cache"
}
}
}
View
struct CacheBootcamp: View {
@StateObject var vm = CacheViewModel()
var body: some View {
NavigationView {
VStack {
if let image = vm.startingImage {
Image(uiImage: image)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipped()
.cornerRadius(10)
}
Text(vm.infoMessage)
.font(.headline)
.foregroundColor(.purple)
HStack {
Button("Save to cache") {
vm.saveToCache()
}
.foregroundColor(.white)
.font(.headline)
.padding()
.background(Color.blue)
.cornerRadius(10)
Button("Delete from cache") {
vm.removeFromCache()
}
.foregroundColor(.white)
.font(.headline)
.padding()
.background(Color.red)
.cornerRadius(10)
}
Button("Get from cache") {
vm.getFromCache()
}
.foregroundColor(.white)
.font(.headline)
.padding()
.background(Color.green)
.cornerRadius(10)
if let cachedImage = vm.cachedImage {
Image(uiImage: cachedImage)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipped()
.cornerRadius(10)
}
Spacer()
}
.navigationTitle("Cache Bootcamp")
}
}
}
Cache vs FileManager — qaysi biri qachon
| Xususiyat | NSCache | FileManager |
|---|---|---|
| Saqlash joyi | RAM (xotira) | Disk (fayl tizimi) |
| Ilova yopilganda | O'chib ketadi | Qoladi |
| Tezlik | Juda tez | Biroz sekinroq |
| Hajm nazorati | Avtomatik (countLimit) | Qo'lda nazorat |
| Ishlatilish | Sessiya davomida qayta keladigan ma'lumotlar | Doimiy saqlash kerak bo'lgan fayllar |
Keshning ishlash mantig'i (amaliy)
Foydalanuvchi profil sahifasini ochadi
↓
Cache-dan tekshirish: manager.get(name: userId)
├── Topildi → Rasmni ko'rsatish (internet kerak emas)
└── Topilmadi
↓
Internetdan yuklash
↓
Cache-ga saqlash: manager.add(image: image, name: userId)
↓
Rasmni ko'rsatish
Bu — keyingi videoda ko'riladigan downloadImageFromURL funksiyasining asosi.
Xulosa
NSCache— Swift-ning o'rnatilgan, xotirada ishlaydigancache tizimicountLimitvatotalCostLimitbilan hajmni nazorat qilingNSString—NSCacheObjective-C-dan kelgani uchunStringo'rnigaNSStringishlatiladi- Cache — vaqtinchalik: ilova qayta ishga tushsa, tozalanadi
- FileManager bilan birgalikda ishlatilganda — eng samarali kesh strategiyasi: avval cache-dan tekshir, yo'q bo'lsa FileManager-dan, yo'q bo'lsa internetdan yukla