- Published on
SwiftUI crypto app — rasmlarni FileManager-ga saqlash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
SwiftUI crypto app — rasmlarni FileManager-ga saqlash
Ushbu darsda biz ilovamizning ishlash tezligi va internet trafigini tejashni yangi bosqichga olib chiqamiz. Hozirgi holatda tangalar ro'yxatini pastga aylantirib, so'ng yana tepaga qaytsak, SwiftUI ro'yxat elementlarini qayta chizadi va rasmlarni internetdan qaytadan yuklaydi.
Buning oldini olish uchun biz yuklangan rasmlarni qurilmaning xotirasiga (Caches papkasiga) LocalFileManager yordamida keshlab (save) qo'yamiz. Keyingi safar rasm so'ralganda, birinchi bo'lib fayllar tizimi tekshiriladi, agar u yerda rasm topilmasa, keyin internetdan yuklanadi.
1. LocalFileManager utility klassini yaratish
Loyihamizning utilities papkasi ichida LocalFileManager.swift faylini yaratamiz. Ushbu klass singleton shaklida loyihalashtiriladi:
import Foundation
import SwiftUI
class LocalFileManager {
// Singleton ob'ekti
static let instance = LocalFileManager()
private init() {}
// Rasm faylini FileManager-ga saqlash
func saveImage(image: UIImage, imageName: String, folderName: String) {
// Agar papka mavjud bo'lmasa, uni yaratamiz
createFolderIfNeeded(folderName: folderName)
// Rasm ma'lumotlarini PNG formatida olamiz
guard
let data = image.pngData(),
let url = getURLForImage(imageName: imageName, folderName: folderName)
else { return }
// Ma'lumotni olingan URL manziliga yozamiz
do {
try data.write(to: url)
} catch let error {
print("Rasm saqlashda xatolik yuz berdi. Image: \(imageName). Error: \(error)")
}
}
// Rasm faylini FileManager-dan olish
func getImage(imageName: String, folderName: String) -> UIImage? {
guard
let url = getURLForImage(imageName: imageName, folderName: folderName),
FileManager.default.fileExists(atPath: url.path) // Fayl mavjudligini tekshiramiz
else { return nil }
// Fayl yo'li orqali UIImage obyektini yaratib qaytaramiz
return UIImage(contentsOfFile: url.path)
}
// Kerak bo'lsa yangi papka yaratish funksiyasi
private func createFolderIfNeeded(folderName: String) {
guard let url = getURLForFolder(folderName: folderName) else { return }
// Papka mavjudligini tekshirib, yo'q bo'lsa yaratamiz
if !FileManager.default.fileExists(atPath: url.path) {
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
} catch let error {
print("Papka yaratishda xatolik yuz berdi. Folder: \(folderName). Error: \(error)")
}
}
}
// Papka uchun URL manzilini olish (CachesDirectory ichida)
private func getURLForFolder(folderName: String) -> URL? {
guard let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
return nil
}
return url.appendingPathComponent(folderName)
}
// Rasm fayli uchun to'liq URL manzilini olish
private func getURLForImage(imageName: String, folderName: String) -> URL? {
guard let folderURL = getURLForFolder(folderName: folderName) else {
return nil
}
return folderURL.appendingPathComponent(imageName + ".png")
}
}
2. CoinImageService-ni kesh tizimiga moslashtirish
Endi services/CoinImageService.swift faylini yangilaymiz. Rasm so'ralganda birinchi bo'lib fileManager tekshiriladi, agar u yerda rasm bo'lmasa, downloadCoinImage() funksiyasi chaqiriladi:
import Foundation
import SwiftUI
import Combine
class CoinImageService {
@Published var image: UIImage? = nil
private var imageSubscription: AnyCancellable?
private let coin: CoinModel
// LocalFileManager havolasi va kesh papkasi nomi
private let fileManager = LocalFileManager.instance
private let folderName = "coin_images"
private let imageName: String
init(coin: CoinModel) {
self.coin = coin
self.imageName = coin.id // Har bir rasm coin id-si bilan nomlanadi (masalan: "bitcoin.png")
getCoinImage()
}
private func getCoinImage() {
// Birinchi bo'lib xotirani (keshni) tekshiramiz
if let savedImage = fileManager.getImage(imageName: imageName, folderName: folderName) {
self.image = savedImage
} else {
// Agar keshda rasm yo'q bo'lsa, internetdan yuklaymiz
downloadCoinImage()
}
}
private func downloadCoinImage() {
guard let url = URL(string: coin.image) else { return }
imageSubscription = NetworkingManager.download(url: url)
.tryMap({ (data) -> UIImage? in
return UIImage(data: data)
})
.sink(receiveCompletion: NetworkingManager.handleCompletion, receiveValue: { [weak self] (returnedImage) in
guard let self = self, let downloadedImage = returnedImage else { return }
// Rasmni view-ga uzatamiz
self.image = downloadedImage
self.imageSubscription?.cancel()
// Yuklangan rasmni kelajak uchun keshga saqlab qo'yamiz
self.fileManager.saveImage(image: downloadedImage, imageName: self.imageName, folderName: self.folderName)
})
}
}
3. Nega aynan CachesDirectory?
Ilovamizda rasmlarni saqlash uchun cachesDirectoryni tanladik. Buning muhim sabablari bor:
- Tizim nazorati: Agar qurilma xotirasi to'lib ketsa, iOS avtomatik ravishda Caches ichidagi keraksiz keshlarni tozalaydi.
- Xavfsizlik: Ilovamiz xotirani to'ldirib yuborishi va tizimni qotirishi oldi olinadi.
- Qayta tiklanish: Agar kesh o'chib ketsa ham, ilovamizda internetdan qayta yuklab olish logikasi (fallback) borligi sababli rasm baribir ekranda ko'rsatiladi.
Endi ilovani ishga tushirib ro'yxatni aylantirsangiz, rasmlar juda tez va tarmoq trafigini umuman sarflamasdan yuklanadi.
Keyingi darsda biz ro'yxat tepasida qidiruv satrini (Search Bar) yaratishni va tangalarni dinamik ravishda qidirishni yo'lga qo'yamiz! 🚀