- Published on
Xcode-da FileManager-ga ma'lumot va rasmlarni saqlash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
FileManager nima va nima uchun kerak
FileManager — iOS qurilmadagi fayl tizimi bilan ishlash imkonini beradi. U Mac-dagi Finder kabi ishlaydi: avval saqlamoqchi bo'lgan papkani topasiz, so'ngra faylni o'sha yerga saqlaymiz va kerak bo'lganda olamiz.
Asosiy farq: biz papkalarda qo'lda navigation qilmaymiz — bularning barchasini dasturiy ravishda kod orqali bajaramiz.
FileManager qachon ishlatiladi
| Vaziyat | Tavsiya |
|---|---|
| Kichik qiymatlar (foydalanuvchi nomi, sozlamalar) | UserDefaults |
| Tuzilgan ma'lumotlar (entity-lar, munosabatlar) | Core Data |
| Rasmlar, videolar, audio, JSON fayllar | FileManager |
Muhim: Core Data-ga to'g'ridan-to'g'ri rasm saqlash mumkin emas — buning uchun FileManager ishlatiladi.
Ehtiyot bo'lish kerak bo'lgan jihatlar
- FileManager foydalanuvchining qurilmasiga saqlaydi
- Saqlanganlar o'chirilgunga qadar qoladi
- Siz, dasturchi sifatida, qayerga saqlayotganingizni doim kuzatishingiz kerak — aks holda eski fayllarni topa olmaysiz va o'chirolmaysiz
Arxitektura
Ushbu video uchun qo'llaniladigan tuzilma:
FileManagerBootcamp (View)
└── FileManagerViewModel (ObservableObject)
└── LocalFileManager (Singleton)
- View — faqat UI
- ViewModel — view-ga xos mantiq
- LocalFileManager — ilovaning istalgan joyidan foydalaniladigan, umumiy fayl boshqarish klassi
Uchta asosiy katalog
// 1. Documents Directory
// Foydalanuvchi yaratgan, qayta tiklab bo'lmaydigan ma'lumotlar uchun
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// 2. Caches Directory (ENG KO'P ISHLATILADIGAN)
// Internetdan yuklab olinadigan, qayta yuklanishi mumkin bo'lgan kontentlar uchun
FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
// 3. Temp Directory
// Faqat vaqtinchalik foydalanish uchun
FileManager.default.temporaryDirectory
Apple-ning rasmiy tavsiyasiga ko'ra:
- Documents: foydalanuvchi tomonidan yaratilgan, qayta tiklab bo'lmaydigan fayllar
- Caches: yuklab olingan kontent (rasmlar, xaritalar, jurnallar) — qayta yuklanishi mumkin
- Temp: faqat vaqtinchalik foydalaniladigan ma'lumotlar
LocalFileManager — singleton class
class LocalFileManager {
static let instance = LocalFileManager()
let folderName = "my_app_images"
init() {
createFolderIfNeeded()
}
}
Papka yaratish
func createFolderIfNeeded() {
guard let path = FileManager
.default
.urls(for: .cachesDirectory, in: .userDomainMask)
.first?
.appendingPathComponent(folderName)
.path else { return }
if !FileManager.default.fileExists(atPath: path) {
do {
try FileManager.default.createDirectory(
atPath: path,
withIntermediateDirectories: true,
attributes: nil
)
print("Success creating folder")
} catch let error {
print("Error creating folder: \(error)")
}
}
}
appendingPathComponent(folderName)— caches katalogi ichiga yangi papkawithIntermediateDirectories: true— ichma-ich papkalar kerak bo'lsa, barchasini yaratadi- Papka allaqachon mavjud bo'lsa — ikki marta yaratilmaydi
URL-ni olish — getPath(for:)
Saqlash, olish va o'chirishda bir xil yo'l ishlatilishi kerak. Shu sababdan, yo'lni hisoblash mantig'ini alohida funksiyaga chiqaramiz:
func getPath(for name: String) -> URL? {
guard let path = FileManager
.default
.urls(for: .cachesDirectory, in: .userDomainMask)
.first?
.appendingPathComponent(folderName)
.appendingPathComponent("\(name).jpg") else {
print("Error getting path")
return nil
}
return path
}
.first?—urls(for:in:)massiv qaytaradi, biz faqat birinchisini olamiz.appendingPathComponent(folderName)— papkamizga kiramiz.appendingPathComponent("\(name).jpg")— fayl nomini qo'shamiz
Rasm saqlash — saveImage(_:name:)
@discardableResult
func saveImage(image: UIImage, name: String) -> String {
guard
let data = image.jpegData(compressionQuality: 1.0),
let path = getPath(for: name)
else {
return "Error getting data"
}
do {
try data.write(to: path)
return "Success saving"
} catch let error {
return "Error saving: \(error)"
}
}
UIImageishlatiladi — rasm ma'lumotlarini view-lar va klaslar orasida uzatish osonroq.Image(SwiftUI komponenti) ma'lumot sifatida ishlatish qiyin.jpegData(compressionQuality:)— UIImage-ni JPEG formatiga o'giradi. PNG uchun.pngData()ishlatiladi.compressionQuality: 1.0— 100% sifat. Kamroq joy egallash uchun0.5ham ishlatsa bo'ladi.- Mavjud fayl ustiga yozilsa — qayta yoziladi (overwrite)
Rasm olish — getImage(name:)
func getImage(name: String) -> UIImage? {
guard
let path = getPath(for: name),
FileManager.default.fileExists(atPath: path.path)
else {
print("Error getting path")
return nil
}
return UIImage(contentsOfFile: path.path)
}
fileExists(atPath:)— fayl mavjudligini tekshiradi (path.path— URL-ni string-ga o'giradi)UIImage(contentsOfFile:)— fayldan UIImage yaratadi
Rasm o'chirish — deleteImage(name:)
@discardableResult
func deleteImage(name: String) -> String {
guard
let path = getPath(for: name),
FileManager.default.fileExists(atPath: path.path)
else {
return "Error getting path"
}
do {
try FileManager.default.removeItem(at: path)
return "Successfully deleted"
} catch let error {
return "Error deleting: \(error)"
}
}
removeItem(at:)— URL versiyasi (string versiyasiremoveItem(atPath:))- Fayl mavjud bo'lmasa — xatolik qaytaradi, ilovani crash qilmaydi
Papka o'chirish — deleteFolder()
Barcha saqlangan rasmlarni bir vaqtda o'chirish uchun — papkaning o'zini o'chirish:
func deleteFolder() {
guard let path = FileManager
.default
.urls(for: .cachesDirectory, in: .userDomainMask)
.first?
.appendingPathComponent(folderName)
.path else { return }
do {
try FileManager.default.removeItem(atPath: path)
print("Success deleting folder")
} catch let error {
print("Error deleting folder: \(error)")
}
}
Papka o'chirilganda, uning ichidagi barcha fayllar ham o'chadi. Ilovani keyingi ochilishida createFolderIfNeeded() papkani qayta yaratadi.
ViewModel
class FileManagerViewModel: ObservableObject {
let manager = LocalFileManager.instance
let imageName: String = "steve_jobs"
@Published var image: UIImage? = nil
@Published var infoMessage: String = ""
init() {
getImageFromAssetsFolder()
}
func getImageFromAssetsFolder() {
image = UIImage(named: imageName)
}
func getImageFromFileManager() {
image = manager.getImage(name: imageName)
}
func saveImage() {
guard let image = image else { return }
infoMessage = manager.saveImage(image: image, name: imageName)
}
func deleteImage() {
infoMessage = manager.deleteImage(name: imageName)
}
}
View
struct FileManagerBootcamp: View {
@StateObject var vm = FileManagerViewModel()
var body: some View {
NavigationView {
VStack {
if let image = vm.image {
Image(uiImage: image)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.clipped()
.cornerRadius(10)
}
HStack {
Button("Save to FM") {
vm.saveImage()
}
.foregroundColor(.white)
.font(.headline)
.padding()
.padding(.horizontal)
.background(Color.blue)
.cornerRadius(10)
Button("Delete from FM") {
vm.deleteImage()
}
.foregroundColor(.white)
.font(.headline)
.padding()
.padding(.horizontal)
.background(Color.red)
.cornerRadius(10)
}
Text(vm.infoMessage)
.font(.largeTitle)
.fontWeight(.semibold)
.foregroundColor(.purple)
Spacer()
}
.navigationTitle("File Manager")
}
}
}
Assets papkasi haqida eslatma
// Assets papkasidagi rasmlar — ilova binary-ga "o'rnatiladi"
// Bu App Store-dagi fayl hajmini oshiradi
// Katta/dinamik rasmlar uchun ishlatmang
// ✅ Assets uchun mos: ikonkalar, logolar, doim kerak bo'ladigan kichik rasmlar
// ❌ Assets uchun mos emas: foydalanuvchi profil rasmlari, Instagram postlari
Xulosa
| Funksiya | Usul |
|---|---|
| Papka yaratish | createDirectory(atPath:withIntermediateDirectories:attributes:) |
| Fayl mavjudligini tekshirish | fileExists(atPath:) |
| Fayl saqlash | data.write(to: url) |
| Fayl olish | UIImage(contentsOfFile: path) |
| Fayl o'chirish | removeItem(at: url) |
| Papka o'chirish | removeItem(atPath: path) |
Asosiy qoida: FileManager-da saqlaganlarni o'zingiz kuzating — qayerga, qaysi nom bilan saqlaysiz, kerak bo'lganda o'sha yo'l orqali topishingiz kerak. getPath(for:) kabi yordamchi funksiyalar bu vazifani osonlashtiradi.