NSFileCoordinator är en Foundation-klass i iOS och macOS som ger säker åtkomst till filer när flera trådar, processer eller tillägg arbetar samtidigt. Enligt Apple Developer Documentation, 2024, förhindrar NSFileCoordinator race conditions vid läsning och skrivning av filer, och garanterar att ingen process läser data medan de ändras av en annan. Koordinatorn används i iCloud Drive, File Provider Extension och alla flertrådade filoperationer.
Huvudpunkter
NSFileCoordinator — är en synkroniseringsmekanism för filåtkomst på operativsystemsnivå, introducerad av Apple i iOS 5 och macOS 10.7 Lion. Till skillnad från traditionella lås (NSLock, pthread_mutex) arbetar koordinatorn på filsystemnivå och kan koordinera åtkomst mellan olika processer, inte bara mellan trådar i en applikation.
Behovet av NSFileCoordinator uppstår från Sandbox-arkitekturen i iOS: varje process (app, tillägg, systemtjänst) arbetar i en isolerad miljö med egen åtkomst till filer. När flera processer försöker läsa och skriva samma fil samtidigt (till exempel vid iCloud Drive-synkronisering), uppstår race conditions utan koordinator: process A läser filen i samma ögonblick som process B redan delvis har skrivit över den.
Enligt WWDC 2023 rekommenderar Apple starkt att använda NSFileCoordinator för alla filoperationer i Ubiquity container (iCloud Drive) och vid arbete med File Provider Extension. Att ignorera koordinering är en av de vanliga orsakerna till dataskador och icke-reproducerbara buggar i iOS-applikationer.
Koordinationsavsikt (NSFileCoordinator.ReadingIntent / WritingIntent) — är ett objekt som deklarerar vilken typ av operation en tråd eller process planerar att utföra. Koordinatorn använder dessa avsikter för att bestämma åtkomstordning och lösa konflikter.
| Typ av avsikt | Beskrivning | När ska den användas |
|---|---|---|
| ReadingIntent | Läsa fil utan ändringar | Öppna dokument, ladda data |
| WritingIntent | Skriva med möjlig innehållsändring | Spara dokument, redigera |
| ReadingIntent(URL, options: .withoutChanges) | Läsa utan att spåra ändringar | Snabb förhandsgranskning av innehåll |
| WritingIntent(URL, options: .contentIndependentMetadataOnly) | Ändra endast metadata | Uppdatera datum eller attribut |
| WritingIntent(URL, options: .forDeleting) | Ta bort fil | Användaren tar bort dokument |
Koordinationsregler: flera samtidiga läsningar är tillåtna (om det inte finns någon aktiv skrivning), skrivning är exklusiv — ingen läsning eller skrivning är tillåten under skrivoperationen. Detta överensstämmer med readers-writer lock-modellen, men med ytterligare stöd för interprocesskoordinering via launchd och XPC.
Viktig nyans: NSFileCoordinator förhindrar inte åtkomst till filen via vanlig NSData eller FileManager — den koordinerar endast de operationer som uttryckligen är inslagna i koordinationsblock. Om en annan tråd får åtkomst till filen direkt, förbi koordinatorn, uppstår precis de race conditions som koordinatorn är avsedd att förhindra.
Grundläggande mönster för att använda NSFileCoordinator består av tre steg: skapa en instans av koordinatorn, deklarera avsikten (läsning eller skrivning) och utföra operationen inuti koordinationsblocket. Koordinatorn garanterar att ingen annan koordinator samtidigt arbetar med samma fil.
import Foundation
let coordinator = NSFileCoordinator()
let fileURL = getDocumentURL()
// Säker läsning
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)
}
// Säker skrivning
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)"
)
}
}
Batchoperation — koordinatorn kan bearbeta flera filer i en enda operation med hjälp av en array av avsikter. Detta är praktiskt för att flytta, kopiera eller ta bort en uppsättning filer som en enda transaktion. Om en av avsikterna inte kan utföras, avbryts hela operationen med ett fel.
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)
}
Asynkron koordinering — från och med iOS 15 stöder NSFileCoordinator asynkrona metoder med completion handler, vilket möjliggör koordinering utan att blockera den anropande tråden. Detta är kritiskt för UI-tråden, där synkron väntan på koordinering kan orsaka att gränssnittet fryser i sekunder.
NSFilePresenter — är ett protokoll som ett objekt implementerar för att ta emot meddelanden om ändringar i filer som koordineras av NSFileCoordinator. Om din applikation visar innehållet i en fil som kan ändras av en annan process (till exempel iCloud Drive synkroniserar en ny version), möjliggör implementering av NSFilePresenter snabb uppdatering av gränssnittet.
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)
}
}
Protokollmetoder: presentedItemDidChange anropas när filens innehåll ändras, presentedItemDidMove(to:) — efter att filen flyttats, accommodatePresentedItemDeletion — innan filen tas bort av en annan process (ger applikationen möjlighet att stänga filen korrekt). Dessutom stöder protokollet versionshantering via presentedItemDidGainVersion: och presentedItemDidLoseVersion:.
Viktigt: NSFilePresenter måste registreras i systemet via NSFileCoordinator.addFilePresenter:. Utan registrering kommer meddelanden inte att levereras. Registrering görs en gång vid applikationsstart och kräver inte omregistrering när presentern återskapas.
Använd alltid koordinatorn för filer i Ubiquity container (iCloud Drive) och kataloger som är tillgängliga för tillägg. Även om applikationen för närvarande är entrådig, kan framtida uppdateringar eller systemändringar lägga till parallell åtkomst, och brist på koordinering kommer att leda till svårhittade buggar.
Minimera tiden i koordinationsblocket. Medan blocket exekveras kan andra processer inte komma åt filen. Långa operationer inuti blocket (komplex databehandling, nätverksförfrågningar) blockerar hela filåtkomstsystemet. Utför endast läsning eller skrivning av data inuti blocket och bearbetning utanför det.
Undvik deadlocks: anropa inte koordinatorn från insidan av ett annat koordinatorblock för samma fil — detta leder till ömsesidig blockering. Använd batchoperationer (array av avsikter) istället för nästlade anrop. Om nästling är nödvändig, använd olika köer eller olika URL:er.
Enligt objc.io (2024) inkluderar typiska fel vid arbete med NSFileCoordinator: brist på felhantering i completion handler (leder till ofullständiga operationer); koordinering endast för skrivning men inte för läsning; användning av föråldrat synkront API i UI-tråden; ignorering av NSFilePresenter-protokollet vid arbete med iCloud Drive. Det sista felet är det lömskaste: applikationen visar inaktuell data utan att veta att filen redan har ändrats.
Vanliga frågor
NSFileCoordinator — Foundation-klass för säker filåtkomst från flera trådar eller processer. Förhindrar race conditions genom att koordinera läs- och skrivoperationer på filsystemnivå.
NSLock fungerar endast inom en process (mellan trådar). NSFileCoordinator koordinerar åtkomst mellan olika processer och tillägg, inklusive iCloud Drive-synkronisering och File Provider Extension.
Ja, Apple rekommenderar starkt att använda NSFileCoordinator för alla filoperationer i Ubiquity container. Utan koordinator är dataskada möjlig vid synkronisering mellan enheter och konflikter med File Provider Extension.
NSFilePresenter — protokoll för att ta emot meddelanden om filändringar. Gör det möjligt för applikationen att reagera på ändringar gjorda av andra processer: uppdatera UI vid modifiering, hantera flyttning eller förbereda sig för borttagning av fil.
Fem typer: ReadingIntent (läsning), WritingIntent (skrivning), ReadingIntent med .withoutChanges (läsning utan spårning), WritingIntent med .contentIndependentMetadataOnly (endast metadata) och WritingIntent med .forDeleting (borttagning). Varje typ bestämmer åtkomstnivån till filen.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också