NSFileCoordinator iOS va macOS-da Foundation sinfi bo'lib, bir vaqtning o'zida bir nechta oqim, jarayon yoki kengaytma ishlaganda fayllarga xavfsiz kirishni ta'minlaydi. Apple Developer Documentation, 2024-ga ko'ra, NSFileCoordinator fayllarni o'qish va yozishda race condition-larning oldini oladi, hech qanday jarayon boshqasi tomonidan o'zgartirilayotgan ma'lumotlarni o'qimasligini kafolatlaydi. Koordinator iCloud Drive, File Provider Extension va barcha ko'p oqimli fayl operatsiyalarida qo'llaniladi.
Asosiy ma'lumotlar
NSFileCoordinator — Apple tomonidan iOS 5 va macOS 10.7 Lion-da taqdim etilgan, operatsion tizim darajasida fayl kirish sinxronizatsiyasi mexanizmidir. An'anaviy blokirovkalardan (NSLock, pthread_mutex) farqli o'laroq, koordinator fayl tizimi darajasida ishlaydi va faqat bitta ilovaning oqimlari o'rtasida emas, balki turli jarayonlar o'rtasida kirishni muvofiqlashtira oladi.
NSFileCoordinator-ga ehtiyoj iOS-dagi Sandbox arxitekturasidan kelib chiqadi: har bir jarayon (ilova, kengaytma, tizim xizmati) fayllarga o'z kirishiga ega bo'lgan izolyatsiya qilingan muhitda ishlaydi. Bir nechta jarayon bir vaqtning o'zida bir faylni o'qish va yozishga urinishganda (masalan, iCloud Drive sinxronizatsiyasi paytida), koordinator bo'lmasa race condition-lar yuzaga keladi: jarayon A faylni jarayon B uni qisman qayta yozgan paytda o'qiydi.
WWDC 2023-ga ko'ra, Apple Ubiquity container (iCloud Drive) va File Provider Extension bilan ishlashda barcha fayl operatsiyalari uchun NSFileCoordinator-dan foydalanishni qat'iy tavsiya qiladi. Muvofiqlashtirishga e'tibor bermaslik iOS ilovalarida ma'lumotlarning buzilishi va takrorlanmaydigan xatolarning keng tarqalgan sabablaridan biridir.
Muvofiqlashtirish intenti (NSFileCoordinator.ReadingIntent / WritingIntent) — oqim yoki jarayon bajarishni rejalashtirgan operatsiya turini e'lon qiluvchi ob'ektdir. Koordinator ushbu intentlardan kirish tartibini aniqlash va konfliktlarni hal qilish uchun foydalanadi.
| Intent turi | Tavsif | Qachon ishlatish kerak |
|---|---|---|
| ReadingIntent | Faylni o'zgartirmasdan o'qish | Hujjatni ochish, ma'lumotlarni yuklash |
| WritingIntent | Mazmunni o'zgartirish bilan yozish | Hujjatni saqlash, tahrirlash |
| ReadingIntent(URL, options: .withoutChanges) | O'zgarishlarni kuzatmasdan o'qish | Mazmunni tez ko'rish |
| WritingIntent(URL, options: .contentIndependentMetadataOnly) | Faqat metama'lumotlarni o'zgartirish | Sana yoki atributlarni yangilash |
| WritingIntent(URL, options: .forDeleting) | Faylni o'chirish | Foydalanuvchi tomonidan hujjatni o'chirish |
Muvofiqlashtirish qoidalari: bir nechta parallel o'qishga ruxsat beriladi (agar faol yozish bo'lmasa), yozish eksklyuzivdir — yozish operatsiyasi paytida hech qanday o'qish yoki yozishga ruxsat berilmaydi. Bu readers-writer lock modeliga mos keladi, ammo launchd va XPC orqali jarayonlararo muvofiqlashtirish uchun qo'shimcha qo'llab-quvvatlash bilan.
Muhim nuance: NSFileCoordinator oddiy NSData yoki FileManager orqali faylga kirishni oldini olmaydi — u faqat muvofiqlashtirish bloklariga aniq o'ralgan operatsiyalarni muvofiqlashtiradi. Agar boshqa oqim koordinatorni chetlab o'tib, to'g'ridan-to'g'ri faylga kira olsa, koordinator oldini olishi kerak bo'lgan race condition-lar yuzaga keladi.
Asosiy naqsh NSFileCoordinator-dan foydalanish uch bosqichdan iborat: koordinator nusxasini yaratish, intentni e'lon qilish (o'qish yoki yozish) va muvofiqlashtirish bloki ichida operatsiyani bajarish. Koordinator boshqa hech qanday koordinator bir vaqtning o'zida bir xil fayl bilan ishlamasligini kafolatlaydi.
import Foundation
let coordinator = NSFileCoordinator()
let fileURL = getDocumentURL()
// Xavfsiz o'qish
let readIntent = NSFileCoordinator
.ReadingIntent(url: fileURL)
var content: Data?
var readError: NSError?
coordinator.coordinate(with: readIntent) { error in
if let error = error {
readError = error
return
}
content = try? Data(contentsOf: fileURL)
}
// Xavfsiz yozish
let writeIntent = NSFileCoordinator
.WritingIntent(url: fileURL)
coordinator.coordinate(with: writeIntent) { error in
guard error == nil else { return }
do {
try newData.write(to: fileURL)
} catch {
Logger.storage.error(
"Write failed: \(error)"
)
}
}
Guruhli operatsiya — koordinator intentlar massividan foydalanib, bitta operatsiyada bir nechta faylni qayta ishlashi mumkin. Bu fayllar to'plamini yagona tranzaksiya sifatida ko'chirish, nusxalash yoki o'chirish uchun qulaydir. Agar intentlardan biri bajarilmasa, butun operatsiya xato bilan bekor qilinadi.
let coordinator = NSFileCoordinator()
let readIntent = NSFileCoordinator
.ReadingIntent(url: sourceURL)
let writeIntent = NSFileCoordinator
.WritingIntent(url: destURL)
coordinator.coordinate(
with: [readIntent, writeIntent]
) { error in
try? FileManager.default
.copyItem(at: sourceURL, to: destURL)
}
Asinxron muvofiqlashtirish — iOS 15 dan boshlab, NSFileCoordinator completion handler bilan asinxron metodlarni qo'llab-quvvatlaydi, bu chaqiruvchi oqimni bloklamasdan muvofiqlashtirishni amalga oshirishga imkon beradi. Bu UI oqimi uchun juda muhim, chunki sinxron kutish interfeysning soniyalar davomida muzlashiga olib kelishi mumkin.
NSFilePresenter — NSFileCoordinator tomonidan muvofiqlashtirilgan fayllardagi o'zgarishlar haqida bildirishnomalar olish uchun ob'ekt amalga oshiradigan protokoldir. Agar ilovangiz boshqa jarayon tomonidan o'zgartirilishi mumkin bo'lgan fayl mazmunini ko'rsatsa (masalan, iCloud Drive yangi versiyani sinxronlashtiradi), NSFilePresenter-ni amalga oshirish interfeysni o'z vaqtida yangilash imkonini beradi.
class DocumentPresenter: NSFilePresenter {
let presentedItemURL: URL?
let presentedItemOperationQueue: OperationQueue
init(url: URL) {
presentedItemURL = url
presentedItemOperationQueue = OperationQueue()
}
func presentedItemDidChange() {
DispatchQueue.main.async {
NotificationCenter.default
.post(name: .documentDidChange,
object: self)
}
}
func presentedItemDidMove(to newURL: URL) {
Logger.storage.info(
"File moved to: \(newURL.lastPathComponent)"
)
}
func accommodatePresentedItemDeletion(
completionHandler: @escaping (Error?) -> Void
) {
Logger.storage.warn("File deleted externally")
completionHandler(nil)
}
}
Protokol metodlari: presentedItemDidChange fayl mazmuni o'zgarganda chaqiriladi, presentedItemDidMove(to:) — fayl ko'chirilgandan so'ng, accommodatePresentedItemDeletion — fayl boshqa jarayon tomonidan o'chirilishidan oldin (ilovaga faylni to'g'ri yopish imkonini beradi). Qo'shimcha ravishda, protokol presentedItemDidGainVersion: va presentedItemDidLoseVersion: orqali versiyalashni qo'llab-quvvatlaydi.
Muhim: NSFilePresenter tizimda NSFileCoordinator.addFilePresenter: orqali ro'yxatdan o'tkazilishi kerak. Ro'yxatdan o'tkazilmasa, bildirishnomalar yetkazilmaydi. Ro'yxatdan o'tkazish ilova ishga tushganda bir marta amalga oshiriladi va presenter qayta yaratilganda qayta ro'yxatdan o'tish talab qilinmaydi.
Har doim koordinatordan foydalaning Ubiquity container (iCloud Drive) va kengaytmalar uchun mavjud kataloglardagi fayllar uchun. Hozirda ilova bir oqimli bo'lsa ham, kelajakdagi yangilanishlar yoki tizim o'zgarishlari parallel kirishni qo'shishi mumkin va muvofiqlashtirishning yo'qligi qiyin aniqlanadigan xatolarga olib keladi.
Muvofiqlashtirish blokidagi vaqtni minimallashtiring. Blok bajarilayotganda, boshqa jarayonlar faylga kira olmaydi. Blok ichidagi uzoq operatsiyalar (murakkab ma'lumotlarni qayta ishlash, tarmoq so'rovlari) butun fayl kirish tizimini bloklaydi. Blok ichida faqat ma'lumotlarni o'qish yoki yozishni bajaring, qayta ishlashni esa blokdan tashqarida amalga oshiring.
Deadlock-lardan saqlaning: bir xil fayl uchun boshqa koordinator bloki ichida koordinatorni chaqirmang — bu o'zaro blokirovkaga olib keladi. Ichma-ich chaqiruvlar o'rniga guruhli operatsiyalardan (intentlar massivi) foydalaning. Agar ichma-ichlik zarur bo'lsa, turli navbatlar yoki turli URL-lardan foydalaning.
objc.io (2024)-ga ko'ra, NSFileCoordinator bilan ishlashda odatiy xatolarga quyidagilar kiradi: completion handler-da xatolarni boshqarmaslik (tugallanmagan operatsiyalarga olib keladi); faqat yozish uchun muvofiqlashtirish, lekin o'qish uchun emas; UI oqimida eskirgan sinxron API-dan foydalanish; iCloud Drive bilan ishlashda NSFilePresenter protokoliga e'tibor bermaslik. Oxirgi xato eng makkoridir: ilova eskirgan ma'lumotlarni ko'rsatadi, fayl allaqachon o'zgartirilganligini bilmagan holda.
Tez-tez beriladigan savollar
NSFileCoordinator — bir nechta oqim yoki jarayonlardan fayllarga xavfsiz kirish uchun Foundation sinfi. Fayl tizimi darajasida o'qish va yozish operatsiyalarini muvofiqlashtirib, race condition-larning oldini oladi.
NSLock faqat bitta jarayon ichida (oqimlar o'rtasida) ishlaydi. NSFileCoordinator turli jarayonlar va kengaytmalar o'rtasida kirishni muvofiqlashtiradi, jumladan iCloud Drive sinxronizatsiyasi va File Provider Extension.
Ha, Apple Ubiquity container fayllari bilan barcha operatsiyalar uchun NSFileCoordinator-dan foydalanishni qat'iy tavsiya qiladi. Koordinator bo'lmasa, qurilmalar o'rtasida sinxronizatsiya paytida ma'lumotlarning buzilishi va File Provider Extension bilan konfliktlar mumkin.
NSFilePresenter — fayl o'zgarishlari haqida bildirishnomalar olish uchun protokol. Ilovaga boshqa jarayonlar tomonidan qilingan o'zgarishlarga reaksiya ko'rsatish imkonini beradi: o'zgartirishda UI-ni yangilash, ko'chirishni boshqarish yoki faylni o'chirishga tayyorgarlik ko'rish.
Besh tur: ReadingIntent (o'qish), WritingIntent (yozish), .withoutChanges bilan ReadingIntent (kuzatmasdan o'qish), .contentIndependentMetadataOnly bilan WritingIntent (faqat metama'lumotlar) va .forDeleting bilan WritingIntent (o'chirish). Har biri faylga kirish darajasini belgilaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.