Доступ к рабочему столу в изолированном приложении
Я создаю приложение, которое имеет функцию, чтобы открыть новые снятые скриншоты. Я хотел бы распространять его с помощью Mac App Store. К сожалению, это должно быть в песочнице.
Чтобы найти новые скриншоты, я запускаю NSMetaDataQuery. Он возвращает несколько записей, но, к сожалению, я не могу получить их URL, так как они находятся на рабочем столе (из песочницы моего приложения).
Как я могу это исправить?
Вот часть кода
query = [[NSMetadataQuery alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidStartGatheringNotification object:query];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidUpdateNotification object:query];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query setDelegate:self];
[query setPredicate:[NSPredicate predicateWithFormat:@"kMDItemIsScreenCapture = 1"]];
[query startQuery];
numberOfScreenshots = [query resultCount];
[self uploadToAmazonS3:[[[query results]objectAtIndex:([query resultCount]-1)]valueForAttribute:NSMetadataItemURLKey]];
Спасибо
2 ответа
Не спрашивая разрешения пользователя, вы можете получить доступ только к папкам Музыка, Фильмы, Изображения и Загрузка.
Вы должны попросить пользователя предоставить вам доступ к Папке рабочего стола. Затем используйте механизм под названием Security-Scoped Bookmarks, узнайте больше об этом в AppSandboxDesignGuide.
- Используйте NSOpenPanel, чтобы выбрать каталог.
- Сохраните закладку для будущего использования, например, в NSUserDefaults.
- Получить доступ
1 и 2
NSOpenPanel *openPanel = [[NSOpenPanel alloc] init];
[openPanel setCanChooseFiles:NO];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanCreateDirectories:YES];
[openPanel beginWithCompletionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
for (NSURL *fileURL in [openPanel URLs]) {
NSString *filename = [fileURL path];
[[NSUserDefaults standardUserDefaults] setObject:filename forKey:@"PathToFolder"];
NSError *error = nil;
NSData *bookmark = [fileURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
if (error) {
NSLog(@"Error creating bookmark for URL (%@): %@", fileURL, error);
[NSApp presentError:error];
} else {
[[NSUserDefaults standardUserDefaults] setObject:bookmark forKey:@"PathToFolder"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
break;
}
}
}];
3.
NSError *error = nil;
NSData *bookmark = [[NSUserDefaults standardUserDefaults] objectForKey:@"PathToFolder"];
bookmarkedURL = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:nil error:&error];
BOOL ok = [bookmarkedURL startAccessingSecurityScopedResource];
NSLog(@"Accessed ok: %d %@", ok, [bookmarkedURL relativePath]);
Так что это должно быть.
После того, как вы разрешили доступ, вам также необходимо получить путь к реальной домашней папке - все остальные файловые API предоставляют путь только к папке с песочницей, даже если доступ к реальной папке уже включен. Чтобы обойти эту досадную проблему, Apple рекомендует сделать это, чтобы получить настоящую домашнюю папку:
#include <sys/types.h>
#include <pwd.h>
const char *home = getpwuid(getuid())->pw_dir;
NSString *path = [[NSFileManager defaultManager]
stringWithFileSystemRepresentation:home
length:strlen(home)];
NSString *realHomeDirectory = [[NSURL fileURLWithPath:path isDirectory:YES] path];