NSFileCoordinator — coordinamento accesso ai file in iOS

Autore: IT Sectr Pubblicato: 2026-07-11 Tempo di lettura: 7 min

NSFileCoordinator è una classe Foundation in iOS e macOS che garantisce un accesso sicuro ai file quando più thread, processi o estensioni lavorano simultaneamente. Secondo la Documentazione per Sviluppatori Apple, 2024, NSFileCoordinator previene le condizioni di gara durante la lettura e scrittura di file, garantendo che nessun processo legga dati mentre un altro li sta modificando. Il coordinatore è utilizzato in iCloud Drive, File Provider Extension e qualsiasi operazione di file multithread.

Punti chiave

  • NSFileCoordinator — una classe per l'accesso sicuro ai file da più thread e processi
  • Intenzioni di coordinamento (reading/writing intent) dichiarano il tipo di operazione prima dell'esecuzione
  • Prevenzione delle condizioni di gara — il compito principale del coordinatore nell'accesso parallelo
  • Supporto File Provider — il coordinatore è obbligatorio quando si lavora con file iCloud Drive ed estensioni
  • NSFilePresenter — un protocollo per ricevere notifiche sulle modifiche ai file da altri processi

Cos'è NSFileCoordinator?

NSFileCoordinator è un meccanismo di sincronizzazione dell'accesso ai file a livello di sistema operativo, introdotto da Apple in iOS 5 e macOS 10.7 Lion. A differenza dei blocchi tradizionali (NSLock, pthread_mutex), il coordinatore opera a livello di filesystem e può coordinare l'accesso tra diversi processi, non solo tra thread della stessa applicazione.

La necessità di NSFileCoordinator deriva dall'architettura Sandbox in iOS: ogni processo (applicazione, estensione, servizio di sistema) viene eseguito in un ambiente isolato con il proprio accesso ai file. Quando più processi tentano di leggere e scrivere lo stesso file simultaneamente (ad esempio, durante la sincronizzazione di iCloud Drive), senza un coordinatore si verificano condizioni di gara: il processo A legge il file mentre il processo B lo ha già parzialmente sovrascritto.

Secondo la WWDC 2023, Apple raccomanda vivamente di utilizzare NSFileCoordinator per tutte le operazioni sui file nel container Ubiquity (iCloud Drive) e quando si lavora con File Provider Extension. Ignorare il coordinamento è una delle cause comuni di corruzione dei dati e bug non riproducibili nelle applicazioni iOS.

Tipi di intenzioni di coordinamento

Intenzione di coordinamento (NSFileCoordinator.ReadingIntent / WritingIntent) è un oggetto che dichiara il tipo di operazione che un thread o processo intende eseguire. Il coordinatore utilizza queste intenzioni per determinare l'ordine di accesso e risolvere i conflitti.

Tipo di intenzioneDescrizioneQuando usarlo
ReadingIntentLettura del file senza modificheAprire un documento, caricare dati
WritingIntentScrittura con possibile modifica del contenutoSalvare un documento, modificare
ReadingIntent(URL, options: .withoutChanges)Lettura senza tracciamento delle modificheAnteprima rapida del contenuto
WritingIntent(URL, options: .contentIndependentMetadataOnly)Modifica solo dei metadatiAggiornare data o attributi
WritingIntent(URL, options: .forDeleting)Eliminazione del fileEliminazione del documento da parte dell'utente

Regole di coordinamento: sono consentite più letture simultanee (se non c'è scrittura attiva), la scrittura è esclusiva — nessuna lettura o scrittura è consentita durante un'operazione di scrittura. Questo segue il modello di blocco lettori-scrittori, ma con supporto aggiuntivo per il coordinamento tra processi tramite launchd e XPC.

Sfumatura importante: NSFileCoordinator non impedisce l'accesso ai file tramite NSData o FileManager normali — coordina solo le operazioni che sono esplicitamente racchiuse in blocchi di coordinamento. Se un altro thread accede direttamente al file senza il coordinatore, si verificano esattamente le condizioni di gara che il coordinatore è progettato per prevenire.

NSFileCoordinator in azione: esempi di codice

Schema di base per l'utilizzo di NSFileCoordinator consiste in tre passaggi: creare un'istanza del coordinatore, dichiarare un'intenzione (lettura o scrittura) ed eseguire l'operazione all'interno di un blocco di coordinamento. Il coordinatore garantisce che nessun altro coordinatore lavori simultaneamente con lo stesso file.

swift
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)"
        )
    }
}

Operazione batch — il coordinatore può gestire più file in una singola operazione utilizzando un array di intenzioni. Questo è comodo per spostare, copiare o eliminare un insieme di file come un'unica transazione. Se una delle intenzioni non può essere soddisfatta, l'intera operazione viene annullata con un errore.

swift
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)
}

Coordinamento asincrono — a partire da iOS 15, NSFileCoordinator supporta metodi asincroni con un gestore di completamento, consentendo il coordinamento senza bloccare il thread chiamante. Questo è fondamentale per il thread UI, dove l'attesa sincrona per il coordinamento può congelare l'interfaccia per secondi.

Protocollo NSFilePresenter e notifiche

NSFilePresenter è un protocollo che un oggetto implementa per ricevere notifiche sulle modifiche ai file coordinati da NSFileCoordinator. Se la tua applicazione visualizza il contenuto di un file che può essere modificato da un altro processo (ad esempio, iCloud Drive sincronizza una nuova versione), implementare NSFilePresenter consente di aggiornare tempestivamente l'interfaccia.

swift
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)
    }
}

Metodi del protocollo: presentedItemDidChange viene chiamato quando il contenuto del file cambia, presentedItemDidMove(to:) — dopo lo spostamento del file, accommodatePresentedItemDeletion — prima dell'eliminazione del file da parte di un altro processo (consente all'applicazione di chiudere correttamente il file). Inoltre, il protocollo supporta il versionamento tramite presentedItemDidGainVersion: e presentedItemDidLoseVersion:.

Importante: NSFilePresenter deve essere registrato nel sistema tramite NSFileCoordinator.addFilePresenter:. Senza registrazione, le notifiche non verranno consegnate. La registrazione viene effettuata una volta all'avvio dell'applicazione e non richiede una nuova registrazione quando il presentatore viene ricreato.

Migliori pratiche di coordinamento dei file

Usa sempre il coordinatore per i file nel container Ubiquity (iCloud Drive) e nelle directory accessibili alle estensioni. Anche se l'applicazione è attualmente single-thread, futuri aggiornamenti o modifiche di sistema potrebbero aggiungere accesso parallelo, e la mancanza di coordinamento porterà a bug difficili da trovare.

Minimizza il tempo all'interno del blocco di coordinamento. Mentre il blocco è in esecuzione, altri processi non possono accedere al file. Operazioni lunghe all'interno del blocco (elaborazione complessa di dati, richieste di rete) bloccano l'intero sistema di accesso ai file. Esegui solo lettura o scrittura di dati all'interno del blocco e l'elaborazione all'esterno.

Evita deadlock: non chiamare il coordinatore dall'interno del blocco di un altro coordinatore per lo stesso file — ciò causerà un deadlock reciproco. Utilizza operazioni batch (array di intenzioni) invece di chiamate annidate. Se l'annidamento è necessario, utilizza code diverse o URL diversi.

Secondo objc.io (2024), gli errori tipici quando si lavora con NSFileCoordinator includono: mancanza di gestione degli errori nel gestore di completamento (porta a operazioni incomplete); coordinamento solo per le scritture ma non per le letture; utilizzo della vecchia API sincrona sul thread UI; ignorare il protocollo NSFilePresenter quando si lavora con iCloud Drive. L'ultimo errore è il più insidioso: l'applicazione mostra dati obsoleti senza rendersi conto che il file è già stato modificato.

Domande frequenti

Cos'è NSFileCoordinator?

NSFileCoordinator è una classe Foundation per l'accesso sicuro ai file da più thread o processi. Previene le condizioni di gara coordinando le operazioni di lettura e scrittura a livello di filesystem.

Qual è la differenza tra NSFileCoordinator e NSLock?

NSLock funziona solo all'interno di un singolo processo (tra thread). NSFileCoordinator coordina l'accesso tra diversi processi ed estensioni, inclusa la sincronizzazione di iCloud Drive e File Provider Extension.

È obbligatorio usare NSFileCoordinator per iCloud Drive?

, Apple raccomanda vivamente di utilizzare NSFileCoordinator per tutte le operazioni sui file nel container Ubiquity. Senza il coordinatore, possono verificarsi corruzione dei dati durante la sincronizzazione tra dispositivi e conflitti con File Provider Extension.

Cos'è NSFilePresenter?

NSFilePresenter è un protocollo per ricevere notifiche sulle modifiche ai file. Consente all'applicazione di reagire alle modifiche apportate da altri processi: aggiornare l'UI in caso di modifica, gestire lo spostamento o prepararsi all'eliminazione del file.

Quali tipi di intenzione supporta NSFileCoordinator?

Cinque tipi: ReadingIntent (lettura), WritingIntent (scrittura), ReadingIntent con .withoutChanges (lettura senza tracciamento), WritingIntent con .contentIndependentMetadataOnly (solo metadati) e WritingIntent con .forDeleting (eliminazione). Ognuno definisce il livello di accesso al file.

Riepilogo

  • NSFileCoordinator — un meccanismo di sistema per l'accesso sicuro ai file da thread, processi ed estensioni
  • Intenzioni di coordinamento (lettura/scrittura) dichiarano il tipo di operazione prima dell'esecuzione
  • Letture consentite in parallelo, scritture esclusive (modello lettori-scrittori)
  • NSFilePresenter — un protocollo per notifiche sulle modifiche ai file da altri processi
  • iCloud Drive e File Provider richiedono coordinamento obbligatorio per prevenire la corruzione dei dati
  • Minimizza il tempo all'interno del blocco di coordinamento — le operazioni lunghe bloccano l'accesso di altri processi
  • Deadlock prevenuti tramite operazioni batch e evitando chiamate annidate al coordinatore

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche