web-dev-qa-db-ja.com

NSURLを使用したファイルの存在のテスト

Snow Leopardでは、パス名やコアサービスのFSRefではなく、NSURLオブジェクトを使用してファイルを参照する多くの新しいメソッドを導入しました。

ただし、URLベースの方法を見つけることができないタスクが1つあります。ファイルが存在するかどうかをテストすることです。 -[NSFileManager fileExistsAtPath:] 。そのメソッドと同様に、URLが何かを記述している場合、通常のファイル、ディレクトリ、その他のいずれであっても、YESを返す必要があります。

さまざまな リソース値 を検索しようとすることもできますが、ファイルが存在しない場合は存在しないことが明示的に保証されるわけではなく、その一部(たとえば NSURLEffectiveIconKey )コストがかかる場合があります。

NSFileManagerのfileExistsAtPath:、しかし、より現代的な方法がある場合、私はそれを使用することを好む。

Cocoa、CF、またはCore Servicesに、特定のファイル(またはファイル参照)URLが存在するファイルシステムオブジェクトを参照しているかどうかを保証/文書化する簡単なメソッドまたは関数がありますか?

70
Peter Hosey

NSURLには次のメソッドがあります。

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

「ファイルURLが指すリソースに到達できるかどうかを返します。」

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

IOSでは、他の方法を見つけることができませんでした...

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

Swift 2の答えは次のとおりです。

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

特定のファイル(またはファイル参照)URLが存在するファイルシステムオブジェクトを参照しているかどうかを判断することは、リモートリソースにとって本質的にコストがかかります。このCFURLResourceIsReachable()および[NSURL checkResourceIsReachableAndReturnError:] 、それらを使用する場合でも、多くのファイルについては、かなりの遅延オーバーヘッドが見られます。

行うべきことは、有効なリソースのリストを個別に作成するキャッシングを備えた独自の非同期チェックルーチンを実装することです。

それ以外の場合、ヘッダー状態のCFURLResourceIsReachableのメモ:

例は、特定のドキュメントの存在に依存するUI状態の定期的なメンテナンスです。ファイルを開くなどの操作を実行する場合、最初に到達可能性をチェックするよりも、単に操作を試行してエラーを処理する方が効率的です。

2
valexa

NSURLはより多くのローカルファイルシステムを表すことができるため、信頼性のある方法でそれらの存在をテストできる汎用メソッドがあるとは思いません。少なくとも、Cocoaの基礎にはそのような関数は含まれていません(私の知る限り)。

ローカルファイルシステムのみを扱う場合は、NSURLまたはNSFileManagerのカテゴリを作成し、urlExists:メッセージ。 NSURLNSString(正規化されたパス)に変換してから、[NSFileManager fileExistsAtPath:]メッセージ。

1

SwiftではcheckResourceIsReachable()メソッドを使用できますが、残念ながらtrue(ファイルに到達できる場合)を返すか、エラーをスローします(理由を説明します)到達できません)。

代わりにブールのtrue/false値を取得するには、次の構文を使用します。

let exists = (try? inputFile.checkResourceIsReachable()) ?? false

エラーをログに記録する場合:

let exists: Bool
do {
  exists = try inputFile.checkResourceIsReachable()
} catch {
  exists = false
  print(error.localizedDescription)
}

これはコストのかかる操作であり、直後に古くなる可能性があることに注意してください(他のプロセスが存在するかどうかを確認中にディスクファイルを削除またはアンマウントする場合)。

一般に、ファイルが存在するかどうかを確認するのではなく、ファイルの読み取りまたは書き込みを試み、失敗した場合はエラーを処理することをお勧めします。

0
Abhi Beckert