セキュリティ スコープのブックマークから NSURL を解決するときに、ユーザーがそのファイルまたはフォルダーの名前を変更または移動した場合、ブックマークは古くなります。Apple のドキュメントには、古さについて次のように書かれています。
古い
返された場合、YES の場合、ブックマーク データは古くなっています。アプリは、返された URL を使用して新しいブックマークを作成し、保存されている既存のブックマークのコピーの代わりに使用する必要があります。
残念ながら、これがうまくいくことはめったにありません。5% の確率で機能する場合があります。返された URL を使用して新しいブックマークを作成しようとすると、コード 256 のエラーが発生し、コンソールを見ると、更新された URL でファイル読み取りデータを拒否することを示すサンドボックスからのメッセージが表示されます。
注ブックマークの再生成が機能する場合、最初に再生成されたときにのみ機能するようです。フォルダー/ファイルを再度移動/名前変更すると、機能しないようです。
ブックマークを最初に作成して保存する方法
-(IBAction)bookmarkFolder:(id)sender {
_openPanel = [NSOpenPanel openPanel];
_openPanel.canChooseFiles = NO;
_openPanel.canChooseDirectories = YES;
_openPanel.canCreateDirectories = YES;
[_openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
if (_openPanel.URL != nil) {
NSError *error;
NSData *bookmark = [_openPanel.URL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
if (error != nil) {
NSLog(@"Error bookmarking selected URL: %@", error);
return;
}
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:bookmark forKey:@"bookmark"];
}
}];
}
ブックマークを解決するコード
-(void)resolveStoredBookmark {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *bookmark = [userDefaults objectForKey:@"bookmark"];
if (bookmark == nil) {
NSLog(@"No bookmark stored");
return;
}
BOOL isStale;
NSError *error;
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark
options:NSURLBookmarkResolutionWithSecurityScope
relativeToURL:nil
bookmarkDataIsStale:&isStale
error:&error];
if (error != nil) {
NSLog(@"Error resolving URL from bookmark: %@", error);
return;
} else if (isStale) {
if ([url startAccessingSecurityScopedResource]) {
NSLog(@"Attempting to renew bookmark for %@", url);
// NOTE: This is the bit that fails, a 256 error is
// returned due to a deny file-read-data from sandboxd
bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
[url stopAccessingSecurityScopedResource];
if (error != nil) {
NSLog(@"Failed to renew bookmark: %@", error);
return;
}
[userDefaults setObject:bookmark forKey:@"bookmark"];
NSLog(@"Bookmark renewed, yay.");
} else {
NSLog(@"Could not start using the bookmarked url");
}
} else {
NSLog(@"Bookmarked url resolved successfully!");
[url startAccessingSecurityScopedResource];
NSArray *contents = [NSFileManager.new contentsOfDirectoryAtPath:url.path error:&error];
[url stopAccessingSecurityScopedResource];
if (error != nil) {
NSLog(@"Error reading contents of bookmarked folder: %@", error);
return;
}
NSLog(@"Contents of bookmarked folder: %@", contents);
}
}
ブックマークが古い場合、結果として解決された URL は正しい場所を指します。[url startAccessingSecurityScopedResource] が YES を返すという事実にもかかわらず、実際にはファイルにアクセスできません。
古いブックマークに関するドキュメントを誤解しているのかもしれませんが、何かばかげたことをしているだけだと思います。ブックマークされたファイル/フォルダーの名前が変更または移動されるたびに NSOpenPanel をポップすることは、この時点で私の唯一の他のオプションであり、ばかげているようです。
com.apple.security.files.bookmarks.app-scope、com.apple.security.files.user-selected.read-write、およびcom.apple.security.app-sandboxをすべて true に設定していることを追加する必要があります私の資格ファイルに。