NSFilePresenter è un protocollo Foundation che permette a un oggetto di ricevere notifiche sulle modifiche di file e directory nel file system di iOS e macOS. La classe implementa i metodi del protocollo e si registra tramite NSFileCoordinator, dopodiché il sistema chiama automaticamente questi metodi durante qualsiasi operazione con il file tracciato. Secondo la documentazione per sviluppatori Apple (2025), NSFilePresenter viene utilizzato in applicazioni con accesso multi-thread ai documenti per prevenire conflitti di scrittura. Il protocollo deve essere usato in combinazione con NSFileCoordinator — solo così si garantisce un coordinamento di accesso sicuro.
Punti chiave
NSFilePresenter è un protocollo Foundation progettato per tracciare le modifiche di file e directory nei sistemi operativi Apple. Il protocollo definisce un insieme di metodi che l’oggetto osservatore implementa per ricevere notifiche sugli eventi del file system.
Lo scopo principale del protocollo è fornire un accesso sicuro ai file in scenari multi-thread. In iOS e macOS, più processi e thread possono accedere contemporaneamente allo stesso file tramite NSFileCoordinator e NSFilePresenter garantisce che ogni partecipante riceva lo stato dei dati più recente.
Il protocollo è incluso in Foundation da iOS 5.0 e macOS 10.7. Viene utilizzato in applicazioni che lavorano con documenti, database e qualsiasi file che possa essere modificato simultaneamente da fonti diverse — ad esempio, durante la sincronizzazione iCloud o la modifica collaborativa.
Applicazioni basate su documenti — l’area principale di utilizzo di NSFilePresenter. Le applicazioni che lavorano con UIDocument o NSDocument si registrano automaticamente come presentatori tramite NSFileCoordinator. Ciò consente di gestire correttamente i conflitti durante la modifica dello stesso file da più finestre o dispositivi.
Sincronizzazione iCloud — il secondo scenario chiave. Quando un file viene modificato su un dispositivo, iCloud lo sincronizza su tutti i dispositivi connessi. NSFilePresenter notifica l’applicazione di queste modifiche, consentendo aggiornamenti tempestivi dell’interfaccia.
Editor multi-thread — il terzo scenario. Nelle applicazioni in cui le code in background caricano e salvano dati contemporaneamente al lavoro dell’utente, NSFilePresenter previene le condizioni di competizione durante la scrittura e lettura dei file.
Il meccanismo di funzionamento di NSFilePresenter si basa sul modello di delega: l’oggetto implementa i metodi del protocollo, si registra tramite NSFileCoordinator e riceve chiamate ogni volta che il file tracciato cambia. Il sistema stesso determina quando si verifica una modifica e quali metodi invocare.
Il processo inizia quando l’oggetto crea un’istanza di NSFileCoordinator e chiama il metodo del coordinatore, passando l’URL del file. Il coordinatore verifica se ci sono presentatori registrati per questo URL. In caso affermativo, blocca l’accesso in lettura o scrittura e notifica i presentatori del cambiamento imminente tramite i metodi del protocollo.
Dopo il completamento dell’operazione, il coordinatore rilascia il blocco e chiama le notifiche finali. È importante notare che il presentatore non controlla il flusso di esecuzione — reagisce solo agli eventi. NSFileCoordinator è completamente responsabile del coordinamento.
Fase di preparazione — prima di eseguire un’operazione, il coordinatore chiama accommodatePresentedItemDeletion o accommodatePresentedSubitemDeletion. Il presentatore può gestire la situazione o annullare l’operazione restituendo un errore. Questa fase consente all’applicazione di terminare correttamente il lavoro con il file prima che venga modificato.
Fase di notifica — dopo il completamento dell’operazione, il coordinatore chiama presentedItemDidChange o presentedSubitemDidChange. Il presentatore riceve un segnale che il file è cambiato e può rileggerne il contenuto. Per lo spostamento del file, viene chiamato presentedItemDidMoveToURL con la nuova posizione.
Fase di completamento — il coordinatore rilascia tutti i blocchi e libera le risorse. Il presentatore può continuare a lavorare con i dati aggiornati. Tutte e tre le fasi vengono eseguite in modo sincrono in un singolo thread, quindi i metodi del protocollo devono eseguire rapidamente senza operazioni di I/O prolungate.
Il protocollo NSFilePresenter contiene diversi metodi obbligatori e opzionali. L’unica proprietà obbligatoria è presentedItemURL, che restituisce l’URL del file o directory tracciato. Senza questa proprietà, l’oggetto non può essere registrato come presentatore.
presentedItemURL — una proprietà di tipo URL? che deve restituire il percorso del file tracciato. Se l’oggetto traccia più file, la proprietà restituisce l’URL dell’elemento principale. Per le directory, restituisce l’URL della directory.
presentedItemDidChange — chiamato dopo che il contenuto del file tracciato è cambiato. In questo metodo, il presentatore aggiorna il suo stato interno e ricarica i dati. Questo metodo non riceve informazioni su cosa sia cambiato esattamente — solo il fatto del cambiamento.
accommodatePresentedItemDeletion — chiamato prima dell’eliminazione del file. Il presentatore può salvare lo stato corrente, chiudere i descrittori di file o annullare l’operazione restituendo un NSError. Se il metodo restituisce un errore, l’operazione di eliminazione non viene eseguita.
presentedItemDidMoveToURL — chiamato dopo lo spostamento o la ridenominazione del file. Il metodo riceve il nuovo URL e il presentatore deve aggiornare il riferimento al file. Senza implementare questo metodo, il presentatore continuerà a puntare al vecchio percorso inesistente.
NSFileCoordinator e NSFilePresenter sono una coppia inscindibile. NSFileCoordinator gestisce l’accesso ai file e chiama i metodi del presentatore. Il presentatore non lavora direttamente con il file system — tutte le operazioni passano attraverso il coordinatore, che garantisce l’atomicità delle modifiche.
Il coordinatore registra il presentatore tramite il metodo addFilePresenter della classe NSFileCoordinator. Dopo la registrazione, il presentatore inizia a ricevere notifiche. La rimozione avviene tramite removeFilePresenter. Il sistema mantiene un riferimento debole al presentatore, quindi l’oggetto deve rimanere vivo per tutto il periodo di tracciamento.
Secondo Apple WWDC 2022, NSFileCoordinator utilizza un meccanismo di coordinamento a livello di kernel, garantendo una latenza minima durante i blocchi. Nelle ultime versioni di iOS, il coordinatore è ottimizzato per funzionare con Sandbox e le estensioni delle app.
Intenzione — ogni operazione di lettura o scrittura deve essere racchiusa in un blocco di coordinamento: lettura tramite coordinateReadingItemAtURL, scrittura tramite coordinateWritingItemAtURL. Il coordinatore blocca automaticamente il file per gli altri partecipanti durante l’esecuzione del blocco.
Coordinamento batch — per operazioni che coinvolgono più file, viene utilizzato il coordinamento batch. Il coordinatore blocca atomicamente tutti i file specificati, esegue l’operazione e rilascia i blocchi. Ciò è particolarmente importante quando si spostano o copiano set di documenti.
Creiamo una classe DocumentPresenter che implementa il protocollo NSFilePresenter e traccia le modifiche di un file documento. La classe contiene un riferimento al file, dati interni e un flag di validità.
import Foundation
class DocumentPresenter: NSObject, NSFilePresenter {
var presentedItemURL: URL? {
return self.fileURL
}
var presentedItemOperationQueue: OperationQueue {
return self.queue
}
private let fileURL: URL
private let queue = OperationQueue()
func presentedItemDidChange() {
self.reloadData()
}
func accommodatePresentedItemDeletion() throws {
try self.saveCurrentState()
}
private func reloadData() {
let coordinator = NSFileCoordinator(filePresenter: self)
var error: NSError?
coordinator.coordinate(readingItemAt: self.fileURL,
options: [],
error: &error)
{ readURL in
guard let data = try? Data(contentsOf: readURL)
else { return }
self.processData(data)
}
}
private func processData(_: Data) {
// Elaborazione dati del documento
}
}
La classe implementa presentedItemDidChange per ricaricare i dati quando il file cambia e accommodatePresentedItemDeletion per salvare lo stato prima dell’eliminazione. La coda di operazioni garantisce che tutte le notifiche vengano elaborate in sequenza.
La registrazione del presentatore viene effettuata tramite NSFileCoordinator.addFilePresenter all’apertura di un documento. È importante passare le opzioni di lettura corrette al coordinatore — withoutChanges per operazioni senza modifica o immediatelyAvailable per scenari che richiedono accesso immediato.
Il primo errore comune è la mancata implementazione di presentedItemOperationQueue. Se non si specifica una coda, le notifiche possono arrivare su un thread arbitrario, causando condizioni di competizione dei dati. Utilizzare sempre una OperationQueue sequenziale per elaborare le notifiche.
Il secondo errore è il blocco nei metodi del presentatore. I metodi del protocollo vengono chiamati in modo sincrono dal coordinatore. Se il presentatore esegue un’operazione lunga (scrittura DB, richiesta di rete), blocca il coordinatore per tutti gli altri partecipanti. Spostare le operazioni pesanti nelle code in background.
Il terzo errore è ignorare accommodatePresentedItemDeletion. Se il presentatore non implementa questo metodo e non restituisce un errore, il file può essere eliminato senza salvare lo stato corrente. Salvare sempre i dati in questo metodo se non sono ancora stati scritti su disco.
Il quarto errore è il coordinamento ciclico. Quando il presentatore all’interno di un metodo di notifica chiama nuovamente il coordinatore per lo stesso file, si verifica un deadlock. Verificare il flag isCoordinatedOperation prima di avviare il coordinamento all’interno di un gestore.
| Errore | Conseguenza | Soluzione |
|---|---|---|
| Nessuna coda operazioni | Condizione di competizione nel multi-thread | Specificare OperationQueue |
| Blocco nei metodi | Blocco del coordinatore | Spostare in thread in background |
| Ignorare eliminazione | Perdita di dati durante l’eliminazione | Implementare salvataggio |
| Coordinamento ciclico | Deadlock dell’applicazione | Flag isCoordinatedOperation |
Domande frequenti
NSFileHandle è un’interfaccia di basso livello per leggere e scrivere dati che non fornisce meccanismi di notifica delle modifiche da altri processi. NSFilePresenter funziona a livello di coordinamento: riceve eventi dal sistema ogni volta che un file cambia, indipendentemente dalla fonte — un altro thread, processo o iCloud.
Sì. NSFilePresenter non ha senso senza NSFileCoordinator. Il presentatore definisce solo i metodi di gestione, mentre il coordinatore gestisce i blocchi e chiama questi metodi. Se si utilizza NSFilePresenter senza coordinatore, le notifiche non verranno consegnate.
Può, ma con limitazioni. La proprietà presentedItemURL restituisce un solo URL, quindi per tracciare più file viene utilizzato il protocollo NSFilePresenter con metodi aggiuntivi per sottoelementi. Un’alternativa è creare un’istanza separata di presentatore per ogni file.
NSFilePresenter è completamente compatibile con la sandbox iOS. L’applicazione può tracciare solo i file all’interno del proprio contenitore. Per accedere ai file di altre applicazioni, vengono utilizzati App Groups o Security-Scoped Bookmarks. Il coordinatore opera entro i permessi della sandbox.
Utilizzare debounce o throttle all’interno del metodo presentedItemDidChange. Creare un timer con un ritardo di 0,3–0,5 secondi e resettarlo ad ogni nuova chiamata. Dopo la stabilizzazione, eseguire il ricaricamento dei dati. Ciò impedisce l’elaborazione multipla di un singolo lotto di modifiche.
Riepilogo
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.
Leggi anche