NSFileCoordinator adalah kelas Foundation di iOS dan macOS yang menyediakan akses aman ke file saat beberapa thread, proses, atau ekstensi bekerja secara bersamaan. Menurut Apple Developer Documentation, 2024, NSFileCoordinator mencegah race condition saat membaca dan menulis file, memastikan bahwa tidak ada proses yang membaca data saat sedang diubah oleh proses lain. Koordinator digunakan di iCloud Drive, File Provider Extension, dan semua operasi file multi-thread.
Poin Penting
NSFileCoordinator — adalah mekanisme sinkronisasi akses file di tingkat sistem operasi, diperkenalkan oleh Apple di iOS 5 dan macOS 10.7 Lion. Tidak seperti penguncian tradisional (NSLock, pthread_mutex), koordinator bekerja di tingkat sistem file dan dapat mengoordinasikan akses antara berbagai proses, tidak hanya antar thread dalam satu aplikasi.
Kebutuhan akan NSFileCoordinator muncul dari arsitektur Sandbox di iOS: setiap proses (aplikasi, ekstensi, layanan sistem) bekerja di lingkungan terisolasi dengan akses file sendiri. Ketika beberapa proses mencoba membaca dan menulis file yang sama secara bersamaan (misalnya, saat sinkronisasi iCloud Drive), tanpa koordinator akan muncul race condition: proses A membaca file saat proses B sudah menimpa sebagiannya.
Menurut WWDC 2023, Apple sangat merekomendasikan menggunakan NSFileCoordinator untuk semua operasi file di Ubiquity container (iCloud Drive) dan saat bekerja dengan File Provider Extension. Mengabaikan koordinasi adalah salah satu penyebab umum kerusakan data dan bug yang tidak dapat direproduksi di aplikasi iOS.
Niat koordinasi (NSFileCoordinator.ReadingIntent / WritingIntent) — adalah objek yang mendeklarasikan jenis operasi yang akan dilakukan oleh thread atau proses. Koordinator menggunakan niat ini untuk menentukan urutan akses dan menyelesaikan konflik.
| Jenis niat | Deskripsi | Kapan digunakan |
|---|---|---|
| ReadingIntent | Membaca file tanpa perubahan | Membuka dokumen, memuat data |
| WritingIntent | Menulis dengan kemungkinan perubahan konten | Menyimpan dokumen, mengedit |
| ReadingIntent(URL, options: .withoutChanges) | Membaca tanpa melacak perubahan | Pratinjau cepat konten |
| WritingIntent(URL, options: .contentIndependentMetadataOnly) | Mengubah hanya metadata | Memperbarui tanggal atau atribut |
| WritingIntent(URL, options: .forDeleting) | Menghapus file | Menghapus dokumen oleh pengguna |
Aturan koordinasi: beberapa pembacaan simultan diizinkan (jika tidak ada penulisan aktif), penulisan bersifat eksklusif — tidak ada pembacaan atau penulisan yang diizinkan selama operasi penulisan. Ini sesuai dengan model readers-writer lock, tetapi dengan dukungan tambahan untuk koordinasi antar-proses melalui launchd dan XPC.
Nuansa penting: NSFileCoordinator tidak mencegah akses ke file melalui NSData atau FileManager biasa — ia hanya mengoordinasikan operasi yang secara eksplisit dibungkus dalam blok koordinasi. Jika thread lain mengakses file secara langsung, melewati koordinator, muncullah race condition yang seharusnya dicegah oleh koordinator.
Pola dasar penggunaan NSFileCoordinator terdiri dari tiga langkah: membuat instance koordinator, mendeklarasikan niat (membaca atau menulis), dan menjalankan operasi di dalam blok koordinasi. Koordinator menjamin bahwa tidak ada koordinator lain yang akan bekerja dengan file yang sama secara bersamaan.
import Foundation
let coordinator = NSFileCoordinator()
let fileURL = getDocumentURL()
// Pembacaan aman
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)
}
// Penulisan aman
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)"
)
}
}
Operasi batch — koordinator dapat memproses beberapa file dalam satu operasi menggunakan array niat. Ini berguna untuk memindahkan, menyalin, atau menghapus sekumpulan file sebagai satu transaksi. Jika salah satu niat tidak dapat dilaksanakan, seluruh operasi dibatalkan dengan kesalahan.
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)
}
Koordinasi asinkron — sejak iOS 15, NSFileCoordinator mendukung metode asinkron dengan completion handler, memungkinkan koordinasi dilakukan tanpa memblokir thread pemanggil. Ini sangat penting untuk thread UI, di mana penantian sinkron untuk koordinasi dapat menyebabkan antarmuka membeku selama beberapa detik.
NSFilePresenter — adalah protokol yang diimplementasikan objek untuk menerima notifikasi tentang perubahan file yang dikoordinasikan oleh NSFileCoordinator. Jika aplikasi Anda menampilkan konten file yang dapat diubah oleh proses lain (misalnya, iCloud Drive menyinkronkan versi baru), implementasi NSFilePresenter memungkinkan pembaruan antarmuka tepat waktu.
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)
}
}
Metode protokol: presentedItemDidChange dipanggil saat konten file berubah, presentedItemDidMove(to:) — setelah pemindahan file, accommodatePresentedItemDeletion — sebelum penghapusan file oleh proses lain (memungkinkan aplikasi menutup file dengan benar). Selain itu, protokol mendukung versioning melalui presentedItemDidGainVersion: dan presentedItemDidLoseVersion:.
Penting: NSFilePresenter harus didaftarkan di sistem melalui NSFileCoordinator.addFilePresenter:. Tanpa pendaftaran, notifikasi tidak akan dikirimkan. Pendaftaran dilakukan sekali saat aplikasi dimulai dan tidak memerlukan pendaftaran ulang saat presenter dibuat ulang.
Selalu gunakan koordinator untuk file di Ubiquity container (iCloud Drive) dan direktori yang dapat diakses ekstensi. Bahkan jika aplikasi saat ini single-thread, pembaruan di masa depan atau perubahan sistem dapat menambahkan akses paralel, dan kurangnya koordinasi akan menyebabkan bug yang sulit ditemukan.
Minimalkan waktu dalam blok koordinasi. Saat blok dieksekusi, proses lain tidak dapat mengakses file. Operasi panjang di dalam blok (pemrosesan data kompleks, permintaan jaringan) memblokir seluruh sistem akses file. Lakukan hanya membaca atau menulis data di dalam blok, dan pemrosesan di luarnya.
Hindari deadlock: jangan panggil koordinator dari dalam blok koordinator lain untuk file yang sama — ini akan menyebabkan penguncian mutual. Gunakan operasi batch (array niat) alih-alih panggilan bersarang. Jika bersarang diperlukan, gunakan antrian yang berbeda atau URL yang berbeda.
Menurut objc.io (2024), kesalahan umum saat bekerja dengan NSFileCoordinator meliputi: kurangnya penanganan kesalahan di completion handler (menyebabkan operasi tidak selesai); koordinasi hanya untuk penulisan, tetapi tidak untuk pembacaan; penggunaan API sinkron usang di thread UI; mengabaikan protokol NSFilePresenter saat bekerja dengan iCloud Drive. Kesalahan terakhir adalah yang paling berbahaya: aplikasi menampilkan data usang tanpa mengetahui bahwa file sudah diubah.
Pertanyaan yang Sering Diajukan
NSFileCoordinator — kelas Foundation untuk akses aman ke file dari beberapa thread atau proses. Mencegah race condition dengan mengoordinasikan operasi baca dan tulis di tingkat sistem file.
NSLock hanya bekerja di dalam satu proses (antar thread). NSFileCoordinator mengoordinasikan akses antara berbagai proses dan ekstensi, termasuk sinkronisasi iCloud Drive dan File Provider Extension.
Ya, Apple sangat merekomendasikan penggunaan NSFileCoordinator untuk semua operasi file Ubiquity container. Tanpa koordinator, kemungkinan terjadi kerusakan data saat sinkronisasi antar perangkat dan konflik dengan File Provider Extension.
NSFilePresenter — protokol untuk menerima notifikasi perubahan file. Memungkinkan aplikasi bereaksi terhadap perubahan yang dibuat oleh proses lain: memperbarui UI saat modifikasi, menangani pemindahan, atau bersiap untuk penghapusan file.
Lima jenis: ReadingIntent (membaca), WritingIntent (menulis), ReadingIntent dengan .withoutChanges (membaca tanpa pelacakan), WritingIntent dengan .contentIndependentMetadataOnly (hanya metadata) dan WritingIntent dengan .forDeleting (menghapus). Masing-masing menentukan tingkat akses ke file.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga