NSFileCoordinator iOS və macOS-da Foundation sinfidir, bir neçə thread, proses və ya extension-un eyni vaxtda işləməsi zamanı fayllara təhlükəsiz girişi təmin edir. Apple Developer Documentation, 2024-ə görə, NSFileCoordinator faylların oxunması və yazılması zamanı race condition-ların qarşısını alır, heç bir prosesin digəri tərəfindən dəyişdirilən məlumatları oxumamasını təmin edir. Koordinator iCloud Drive, File Provider Extension və bütün çoxthread-li fayl əməliyyatlarında istifadə olunur.
Əsas məlumatlar
NSFileCoordinator — Apple tərəfindən iOS 5 və macOS 10.7 Lion-da təqdim edilmiş, əməliyyat sistemi səviyyəsində fayl giriş sinxronizasiyası mexanizmidir. Ənənəvi bloklamalardan (NSLock, pthread_mutex) fərqli olaraq, koordinator fayl sistemi səviyyəsində işləyir və yalnız bir tətbiqin thread-ları arasında deyil, müxtəlif proseslər arasında girişi koordinasiya edə bilər.
NSFileCoordinator-a ehtiyac iOS-da Sandbox arxitekturasından yaranır: hər bir proses (tətbiq, extension, sistem xidməti) fayllara öz girişi olan izolyasiya edilmiş mühitdə işləyir. Bir neçə proses eyni faylı eyni anda oxumağa və yazmağa çalışdıqda (məsələn, iCloud Drive sinxronizasiyası zamanı), koordinator olmadan race condition-lar yaranır: proses A faylı o anda oxuyur ki, proses B artıq onu qismən yenidən yazıb.
WWDC 2023-ə görə, Apple Ubiquity container (iCloud Drive) və File Provider Extension ilə işləyərkən bütün fayl əməliyyatları üçün NSFileCoordinator-dan istifadə etməyi qətiliklə tövsiyə edir. Koordinasiyaya məhəl qoymamaq iOS tətbiqlərində məlumatların zədələnməsinin və təkrarlanmayan xətaların ümumi səbəblərindən biridir.
Koordinasiya intenti (NSFileCoordinator.ReadingIntent / WritingIntent) — thread və ya prosesin yerinə yetirməyi planlaşdırdığı əməliyyat növünü bəyan edən obyektdir. Koordinator bu intentlərdən giriş sırasını təyin etmək və konfliktləri həll etmək üçün istifadə edir.
| Intent növü | Təsvir | Nə vaxt istifadə etməli |
|---|---|---|
| ReadingIntent | Faylın dəyişdirilmədən oxunması | Sənədin açılması, məlumatların yüklənməsi |
| WritingIntent | Məzmunun dəyişdirilməsi ilə yazma | Sənədin saxlanması, redaktə |
| ReadingIntent(URL, options: .withoutChanges) | Dəyişiklikləri izləmədən oxuma | Məzmunun sürətli ön baxışı |
| WritingIntent(URL, options: .contentIndependentMetadataOnly) | Yalnız metadatanın dəyişdirilməsi | Tarix və ya atributların yenilənməsi |
| WritingIntent(URL, options: .forDeleting) | Faylın silinməsi | İstifadəçi tərəfindən sənədin silinməsi |
Koordinasiya qaydaları: çoxsaylı eynivaxtlı oxumalara icazə verilir (aktiv yazma yoxdursa), yazma eksklüzivdir — yazma əməliyyatı zamanı heç bir oxuma və ya yazmaya icazə verilmir. Bu readers-writer lock modelinə uyğundur, lakin launchd və XPC vasitəsilə proseslərarası koordinasiya üçün əlavə dəstək ilə.
Vacib nüans: NSFileCoordinator adi NSData və ya FileManager vasitəsilə fayla girişin qarşısını almır — o, yalnız koordinasiya bloklarına açıq şəkildə daxil edilmiş əməliyyatları koordinasiya edir. Əgər başqa bir thread koordinatoru keçərək birbaşa fayla daxil olarsa, koordinatorun qarşısını almaq üçün nəzərdə tutulduğu race condition-lar yaranır.
Əsas nümunə NSFileCoordinator-dan istifadə üç addımdan ibarətdir: koordinator nüsxəsini yaratmaq, intent bəyan etmək (oxuma və ya yazma) və koordinasiya bloku daxilində əməliyyatı yerinə yetirmək. Koordinator heç bir başqa koordinatorun eyni faylla eyni anda işləməyəcəyinə zəmanət verir.
import Foundation
let coordinator = NSFileCoordinator()
let fileURL = getDocumentURL()
// Təhlükəsiz oxuma
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)
}
// Təhlükəsiz yazma
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)"
)
}
}
Toplu əməliyyat — koordinator intentlər massivindən istifadə edərək bir əməliyyatda bir neçə faylı emal edə bilər. Bu, fayllar dəstini vahid əməliyyat kimi köçürmək, kopyalamaq və ya silmək üçün əlverişlidir. Intentlərdən biri yerinə yetirilə bilmirsə, bütün əməliyyat xəta ilə ləğv edilir.
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 koordinasiya — iOS 15-dən etibarən NSFileCoordinator completion handler ilə asinxron metodları dəstəkləyir, bu da çağıran thread-i bloklamadan koordinasiyanı yerinə yetirməyə imkan verir. Bu, UI thread-i üçün kritik əhəmiyyət daşıyır, çünki sinxron gözləmə interfeysin saniyələrlə donmasına səbəb ola bilər.
NSFilePresenter — NSFileCoordinator tərəfindən koordinasiya edilən fayllardakı dəyişikliklər barədə bildirişlər almaq üçün obyektin tətbiq etdiyi protokoldur. Əgər tətbiqiniz başqa bir proses tərəfindən dəyişdirilə bilən faylın məzmununu göstərirsə (məsələn, iCloud Drive yeni versiyanı sinxronlaşdırır), NSFilePresenter tətbiqi interfeysi vaxtında yeniləməyə imkan verir.
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 metodları: presentedItemDidChange faylın məzmunu dəyişdikdə çağırılır, presentedItemDidMove(to:) — fayl köçürüldükdən sonra, accommodatePresentedItemDeletion — fayl başqa proses tərəfindən silinməzdən əvvəl (tətbiqə faylı düzgün bağlamağa imkan verir). Əlavə olaraq, protokol presentedItemDidGainVersion: və presentedItemDidLoseVersion: vasitəsilə versiyalaşdırmanı dəstəkləyir.
Vacib: NSFilePresenter sistemdə NSFileCoordinator.addFilePresenter: vasitəsilə qeydiyyatdan keçməlidir. Qeydiyyat olmadan bildirişlər çatdırılmayacaq. Qeydiyyat tətbiqin başlanğıcında bir dəfə yerinə yetirilir və presenterlərin yenidən yaradılması zamanı təkrar qeydiyyat tələb olunmur.
Həmişə koordinatordan istifadə edin Ubiquity container (iCloud Drive) və extension-lar üçün əlçatan qovluqlardakı fayllar üçün. Hal-hazırda tətbiq təkthread-li olsa belə, gələcək yeniləmələr və ya sistem dəyişiklikləri paralel giriş əlavə edə bilər və koordinasiyanın olmaması çətin aşkarlanan xətalara səbəb olacaq.
Koordinasiya blokunda vaxtı minimuma endirin. Blok icra olunarkən digər proseslər fayla daxil ola bilməz. Blok daxilində uzunmüddətli əməliyyatlar (mürəkkəb məlumat emalı, şəbəkə sorğuları) bütün fayl giriş sistemini bloklayır. Blok daxilində yalnız məlumatların oxunması və ya yazılmasını həyata keçirin, emalı isə blokdan kənarda aparın.
Deadlock-lardan qaçının: eyni fayl üçün başqa koordinatorun bloku daxilində koordinatoru çağırmayın — bu qarşılıqlı bloklamaya səbəb olacaq. İç-içə çağırışlar əvəzinə toplu əməliyyatlardan (intent massivi) istifadə edin. İç-içəlik zəruridirsə, müxtəlif növbələr və ya müxtəlif URL-lərdən istifadə edin.
objc.io (2024)-ə görə, NSFileCoordinator ilə işləyərkən tipik səhvlərə daxildir: completion handler-də xətaların idarə edilməməsi (tamamlanmamış əməliyyatlara gətirib çıxarır); yalnız yazma üçün koordinasiya, lakin oxuma üçün deyil; UI thread-də köhnəlmiş sinxron API-dən istifadə; iCloud Drive ilə işləyərkən NSFilePresenter protokoluna məhəl qoymama. Sonuncu səhv ən təhlükəlidir: tətbiq köhnəlmiş məlumatları göstərir, faylın artıq dəyişdirildiyini bilmədən.
Tez-tez verilən suallar
NSFileCoordinator — bir neçə thread və ya prosesdən fayllara təhlükəsiz giriş üçün Foundation sinfi. Fayl sistemi səviyyəsində oxuma və yazma əməliyyatlarını koordinasiya edərək race condition-ların qarşısını alır.
NSLock yalnız bir proses daxilində (thread-lar arasında) işləyir. NSFileCoordinator müxtəlif proseslər və extension-lar arasında girişi koordinasiya edir, o cümlədən iCloud Drive sinxronizasiyası və File Provider Extension.
Bəli, Apple Ubiquity container faylları ilə bütün əməliyyatlar üçün NSFileCoordinator-dan istifadə etməyi qətiliklə tövsiyə edir. Koordinator olmadan cihazlar arasında sinxronizasiya zamanı məlumatların zədələnməsi və File Provider Extension ilə konfliktlər mümkündür.
NSFilePresenter — fayl dəyişiklikləri barədə bildirişlər almaq üçün protokoldur. Tətbiqə digər proseslər tərəfindən edilən dəyişikliklərə reaksiya verməyə imkan verir: dəyişiklik zamanı UI-ni yeniləmək, köçürməni idarə etmək və ya faylın silinməsinə hazırlaşmaq.
Beş növ: ReadingIntent (oxuma), WritingIntent (yazma), .withoutChanges ilə ReadingIntent (izləmədən oxuma), .contentIndependentMetadataOnly ilə WritingIntent (yalnız metadata) və .forDeleting ilə WritingIntent (silme). Hər biri fayla giriş səviyyəsini təyin edir.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun