NSFileCoordinator, birden çok thread, süreç veya uzantı aynı anda çalışırken güvenli dosya erişimi sağlayan iOS ve macOS'taki bir Foundation sınıfıdır. Apple Geliştirici Dokümantasyonu, 2024'e göre, NSFileCoordinator dosyaları okuma ve yazma sırasında yarış koşullarını önler, hiçbir sürecin başka bir süreç verileri değiştirirken onları okumamasını garanti eder. Koordinatör, iCloud Drive, File Provider Extension ve herhangi bir çok thread'li dosya işleminde kullanılır.
Önemli Noktalar
NSFileCoordinator, Apple tarafından iOS 5 ve macOS 10.7 Lion'da tanıtılan, işletim sistemi düzeyinde bir dosya erişim senkronizasyon mekanizmasıdır. Geleneksel kilitlerden (NSLock, pthread_mutex) farklı olarak, koordinatör dosya sistemi düzeyinde çalışır ve aynı uygulamanın thread'leri arasında değil, farklı süreçler arasındaki erişimi koordine edebilir.
NSFileCoordinator ihtiyacı, iOS'un Sandbox mimarisinden kaynaklanır: her süreç (uygulama, uzantı, sistem servisi) kendi dosya erişimiyle izole bir ortamda çalışır. Birden çok süreç aynı anda aynı dosyayı okumaya ve yazmaya çalıştığında (örneğin, iCloud Drive senkronizasyonu sırasında), koordinatör olmadan yarış koşulları oluşur: süreç A dosyayı okurken süreç B onu kısmen üzerine yazmıştır.
WWDC 2023'e göre Apple, Ubiquity kapsayıcısındaki (iCloud Drive) tüm dosya işlemleri ve File Provider Extension ile çalışırken NSFileCoordinator kullanılmasını şiddetle tavsiye eder. Koordinasyonu göz ardı etmek, iOS uygulamalarında veri bozulmasının ve tekrarlanamayan hataların yaygın nedenlerinden biridir.
Koordinasyon niyeti (NSFileCoordinator.ReadingIntent / WritingIntent), bir thread veya sürecin gerçekleştirmeyi planladığı işlem türünü bildiren bir nesnedir. Koordinatör, erişim sırasını belirlemek ve çakışmaları çözmek için bu niyetleri kullanır.
| Niyet Türü | Açıklama | Ne Zaman Kullanılır |
|---|---|---|
| ReadingIntent | Değişiklik yapmadan dosya okuma | Belge açma, veri yükleme |
| WritingIntent | İçerik değişikliği olasılığıyla yazma | Belge kaydetme, düzenleme |
| ReadingIntent(URL, options: .withoutChanges) | Değişiklik takibi olmadan okuma | Hızlı içerik önizleme |
| WritingIntent(URL, options: .contentIndependentMetadataOnly) | Yalnızca meta verileri değiştirme | Tarih veya nitelikleri güncelleme |
| WritingIntent(URL, options: .forDeleting) | Dosya silme | Kullanıcı tarafından belge silme |
Koordinasyon kuralları: birden çok eşzamanlı okumaya izin verilir (aktif yazma yoksa), yazma özeldir — yazma işlemi sırasında hiçbir okuma veya yazmaya izin verilmez. Bu, okuyucu-yazıcı kilidi modelini izler, ancak launchd ve XPC aracılığıyla süreçler arası koordinasyon için ek destekle birlikte.
Önemli nüans: NSFileCoordinator, normal NSData veya FileManager aracılığıyla dosya erişimini engellemez — yalnızca açıkça koordinasyon bloklarına sarılmış işlemleri koordine eder. Başka bir thread koordinatör olmadan doğrudan dosyaya erişirse, koordinatörün önlemek için tasarlandığı yarış koşullarının aynısı oluşur.
Temel desen NSFileCoordinator kullanımı üç adımdan oluşur: bir koordinatör örneği oluşturun, bir niyet bildirin (okuma veya yazma) ve bir koordinasyon bloğu içinde işlemi gerçekleştirin. Koordinatör, başka hiçbir koordinatörün aynı dosyayla eşzamanlı çalışmayacağını garanti eder.
import Foundation
let coordinator = NSFileCoordinator()
let fileURL = getDocumentURL()
// Safe reading
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)
}
// Safe writing
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 işlem — koordinatör, bir niyet dizisi kullanarak tek bir işlemde birden çok dosyayı işleyebilir. Bu, bir dosya kümesini tek bir işlem olarak taşımak, kopyalamak veya silmek için kullanışlıdır. Niyetlerden biri yerine getirilemezse, tüm işlem bir hatayla iptal 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)
}
Zaman uyumsuz koordinasyon — iOS 15'ten itibaren NSFileCoordinator, bir tamamlanma işleyicisiyle zaman uyumsuz yöntemleri destekleyerek, çağıran thread'i bloke etmeden koordinasyona olanak tanır. Bu, UI thread'i için kritiktir; burada koordinasyon için senkron bekleme, arayüzü saniyelerce dondurabilir.
NSFilePresenter, bir nesnenin NSFileCoordinator tarafından koordine edilen dosyalardaki değişiklikler hakkında bildirim almak için uyguladığı bir protokoldür. Uygulamanız başka bir süreç tarafından değiştirilebilecek bir dosyanın içeriğini görüntülüyorsa (örneğin, iCloud Drive yeni bir sürümü senkronize ediyorsa), NSFilePresenter'ı uygulamak arayüzü zamanında güncellemenizi sağlar.
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 yöntemleri: presentedItemDidChange, dosya içeriği değiştiğinde çağrılır, presentedItemDidMove(to:) — dosya taşındıktan sonra, accommodatePresentedItemDeletion — başka bir süreç tarafından dosya silinmeden önce (uygulamanın dosyayı düzgün bir şekilde kapatmasını sağlar). Ek olarak protokol, presentedItemDidGainVersion: ve presentedItemDidLoseVersion: aracılığıyla sürüm yönetimini destekler.
Önemli: NSFilePresenter, NSFileCoordinator.addFilePresenter: aracılığıyla sisteme kaydedilmelidir. Kayıt olmadan bildirimler iletilmez. Kayıt, uygulama başlangıcında bir kez yapılır ve sunucu yeniden oluşturulduğunda yeniden kayıt gerektirmez.
Koordinatörü her zaman kullanın Ubiquity kapsayıcısındaki (iCloud Drive) ve uzantıların erişebileceği dizinlerdeki dosyalar için. Uygulama şu anda tek thread'li olsa bile, gelecekteki güncellemeler veya sistem değişiklikleri paralel erişim ekleyebilir ve koordinasyon eksikliği bulunması zor hatalara yol açar.
Koordinasyon bloğu içindeki süreyi en aza indirin. Blok yürütülürken diğer süreçler dosyaya erişemez. Blok içindeki uzun işlemler (karmaşık veri işleme, ağ istekleri) tüm dosya erişim sistemini bloke eder. Blok içinde yalnızca veri okuma veya yazma işlemi yapın ve işlemeyi blok dışında gerçekleştirin.
Deadlock'lardan kaçının: aynı dosya için başka bir koordinatörün bloğu içinden koordinatörü çağırmayın — bu karşılıklı deadlock'a neden olur. İç içe çağrılar yerine toplu işlemler (niyet dizisi) kullanın. İç içe geçme gerekiyorsa, farklı kuyruklar veya farklı URL'ler kullanın.
objc.io (2024)'e göre, NSFileCoordinator ile çalışırken tipik hatalar şunları içerir: tamamlanma işleyicisinde hata işleme eksikliği (tamamlanmamış işlemlere yol açar); yalnızca yazma için koordinasyon ancak okuma için değil; UI thread'inde eski senkron API kullanımı; iCloud Drive ile çalışırken NSFilePresenter protokolünü göz ardı etme. Son hata en sinsi olanıdır: uygulama, dosyanın zaten değiştirildiğini fark etmeden eski verileri görüntüler.
Sıkça Sorulan Sorular
NSFileCoordinator, birden çok thread veya süreçten güvenli dosya erişimi için bir Foundation sınıfıdır. Dosya sistemi düzeyinde okuma ve yazma işlemlerini koordine ederek yarış koşullarını önler.
NSLock yalnızca tek bir süreç içinde (thread'ler arasında) çalışır. NSFileCoordinator, iCloud Drive senkronizasyonu ve File Provider Extension dahil olmak üzere farklı süreçler ve uzantılar arasındaki erişimi koordine eder.
Evet, Apple Ubiquity kapsayıcısındaki tüm dosya işlemleri için NSFileCoordinator kullanılmasını şiddetle tavsiye eder. Koordinatör olmadan, cihazlar arasında senkronizasyon sırasında veri bozulması ve File Provider Extension ile çakışmalar meydana gelebilir.
NSFilePresenter, dosya değişiklikleri hakkında bildirim almak için bir protokoldür. Uygulamanın diğer süreçler tarafından yapılan değişikliklere tepki vermesini sağlar: değişiklikte UI güncelleme, taşımayı işleme veya dosya silmeye hazırlanma.
Beş tür: ReadingIntent (okuma), WritingIntent (yazma), .withoutChanges ile ReadingIntent (takipsiz okuma), .contentIndependentMetadataOnly ile WritingIntent (yalnızca meta veriler) ve .forDeleting ile WritingIntent (silme). Her biri dosyaya erişim düzeyini tanımlar.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun