最初に正解を書くとNSStringのファイルパスからNSURLを正しく生成するのは以下のコードです。
1 2 3 |
//正しいコード NSString* string = @"/Users/abt/Documents/日本語のフォルダ名/file.txt"; NSURL* url = [NSURL fileURLWithPath:string]; |
よく間違えやすいのが
1 2 3 |
//間違ったコード1。NSURLが生成されない NSString* string = @"/Users/abt/Documents/日本語のフォルダ名/file.txt"; NSURL* nilUrl = [NSURL URLWithString:string]; // nilが返る |
で、これだと日本語が正しくエスケープ出来ずに引っかかってしまいます。
そこでよく解決策として見かけるのが
1 2 3 |
//間違ったコード2。一見正常にNSURLが作成されたように見えるが…… NSString* escaped = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL* badUrl = [NSURL URLWithString:escaped]; |
というエスケープ処理を施したコードで、確かにNSURLは生成されるのですがイザ実際に動かそうとすると
1 2 3 4 5 6 |
//ファイル生成日時を取得するコードだが失敗する NSError* error = nil; NSDate* badDate = nil, *date = nil; BOOL result; result = [badUrl getResourceValue:&badDate forKey:NSURLCreationDateKey error:&error]; NSLog(@"date:%@, error:%@",badDate, error); |
で、dateはnilが入っているのにerrorはnilのまま, resultもYESが返ってきて正常に動いてる挙動で期待したものが取れていないという厄介な状況に陥ります。これは上記の方法で生成したNSURLはfileスキームが入っていない事が原因と考えられます。
解決方法としては記事の冒頭の通り「fileURLWithPath」でNSURLを取得することで、この場合エスケープは内部で処理されるため、自前で書く必要はありません。
1 2 3 4 5 6 |
//ファイル生成日時を取得するコード。成功する NSURL* url = [NSURL fileURLWithPath:string]; NSError* error = nil; NSDate* date = nil; result = [url getResourceValue:&date forKey:NSURLCreationDateKey error:&error]; NSLog(@"date:%@, error:%@",date, error); |