2009-12-18 13 views
68

Snow Leopard führte viele neue Methoden ein, um NSURL-Objekte für die Bezugnahme auf Dateien, nicht für Pfadnamen oder FSRefs der Kerndienste zu verwenden.Dateiexistenz mit NSURL testen

Es gibt jedoch eine Aufgabe, für die ich keine URL-basierte Methode finden kann: Testen, ob eine Datei existiert. Ich suche nach einer URL-basierten Version von -[NSFileManager fileExistsAtPath:]. Wie diese Methode sollte es YES zurückgeben, wenn die URL irgendetwas beschreibt, sei es eine normale Datei, ein Verzeichnis oder irgendetwas anderes.

Ich könnte versuchen, verschiedene resource values nachschlagen, aber keine von ihnen sind explizit garantiert nicht zu existieren, wenn die Datei nicht, und einige von ihnen (z. B. NSURLEffectiveIconKey) könnte teuer sein, wenn es tut.

Ich könnte einfach NSFileManager fileExistsAtPath: verwenden, aber wenn es eine modernere Methode ist, würde ich es bevorzugen, das zu verwenden.

Gibt es eine einfache Methode oder Funktion in Cocoa, CF oder Core Services, die garantiert/dokumentiert ist, um mir zu sagen, ob eine bestimmte Datei (oder Dateiverweis) URL verweist auf ein Dateisystemobjekt, das existiert?

Antwort

130

NSURL hat diese Methode haben: „Gibt an, ob die Ressource URL durch eine Datei darauf erreicht werden kann“

- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error 

Welche

NSURL *theURL = [NSURL fileURLWithPath:@"/Users/elisevanlooij/nonexistingfile.php" 
       isDirectory:NO]; 
NSError *err; 
if ([theURL checkResourceIsReachableAndReturnError:&err] == NO) 
    [[NSAlert alertWithError:err] runModal]; 
+3

Für alle iPhone OS Devs, die von dieser Antwort abgeworfen werden: 'checkResourceIsReachableAndReturnError:' ist nur in 10.6 und höher verfügbar und noch nicht im iPhone SDK verfügbar. –

+4

Update: Es ist verfügbar ab iOS 4. –

+2

Die iOS-Dokumentation in XCode 3.2.5 (die iOS 4.2 unterstützt) Status: "Diese Methode ist in iOS nicht implementiert, so dass es keine Operation ausführt." – Daniel

1

Da NSURL mehr als lokale Dateisysteme darstellen kann, glaube ich nicht, dass es eine generische Methode gibt, die zuverlässig auf ihre Existenz hin testen kann. Zumindest enthält die Cocoa Foundation keine solche Funktion (soweit ich weiß).

Wenn Sie nur mit lokalen Dateisystemen umgehen, empfehle ich Ihnen mit einer urlExists: Nachricht eine Kategorie für NSURL oder für NSFileManager, zu erstellen. Es würde die NSURL in einen NSString (normalisierten Pfad) umwandeln und dann die [NSFileManager fileExistsAtPath:] Nachricht aufrufen.

+0

Sie können die oben genannten 'checkResourceIsReachableAndReturn 'koppeln Fehler: 'mit' isFileURL', um es vernünftig zu halten. –

2

Ermitteln, ob eine bestimmte Datei (oder Dateiverweis) URL zu einem Objektdatei-System bezieht, die für Remote-Ressourcen von Natur aus teuer ist vorhanden, die 10,6 nur (keine iPhoneOS) api für dieses CFURLResourceIsReachable() und [ NSURL checkResourceIsReachableAndReturnError:] sind beide synchron, selbst wenn Sie sie verwenden würden, würden Sie für viele Dateien immer noch einen erheblichen Zeitaufwand für die Verzögerung sehen.

Was Sie tun sollten, ist Ihre eigene asynchrone Prüfroutine mit Caching implementieren, die separat eine Liste der gültigen Ressourcen erstellt.

Im übrigen gelten die Hinweise für CFURLResourceIsReachable im Header Zustand:

An example would be periodic maintenance of UI state that depends on the existence of a particular document. When performing an operation such as opening a file, it is more efficient to simply try the operation and handle failures than to check first for reachability.

+1

Ich bezweifle, dass es langsam ist ... NSURL behält eine Verbindung zu dem HFS + Dateisystemeintrag bei, den es darstellt. Laut Apple sind URLs * viel * schneller als Pfade für alle Dateisystemoperationen. –

29

Auf iOS ich keinen anderen Weg finden konnte ...

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"file.type"]; 
if ([[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {...} 
9

Hier ist die Swift 2 Antwort:

var error:NSError? 
let folderExists = theURL.checkResourceIsReachableAndReturnError(&error) 
+0

Es sollte 'checkResourceIsReachable() -> Void' sein und Exception werfen, aber was Sie sagten, ist richtig für Xcode 7.x –

+0

* throw error. Schnelle Fehler unterscheiden sich von Objective-C-Ausnahmen. Ähnliche Syntax, aber anderer Zweck. –