Существует проблема с плохо подобранными, несоставными абстракциями в Какао, которые возникают, когда кто-то пытается объединить панель предварительного просмотра Quick Look и URL-адреса в области безопасности.
У меня есть конкретный пример:
Представьте, что мы пытаемся показать предварительный просмотр некоторых объектов из MediaLibrary (MediaLibrary.framework позволяет приложениям просматривать библиотеки iPhoto, Aperture ... и Photos через удобный API).
Самый простой и понятный способ сделать это - адаптировать класс MLMediaObject (который представляет конкретный фото или видео элемент) для реализации протокола QLPreviewItem (который можно передать в QLPreviewPanel):
MLMediaObject + PreviewItem.h
#import <MediaLibrary/MLMediaObject.h>
#import <Quartz/Quartz.h>
@interface MLMediaObject (PreviewItem) <QLPreviewItem>
@end
MLMediaObject + PreviewItem.m
#import "MLMediaObject+PreviewItem.h"
@implementation MLMediaObject (PreviewItem)
- (NSURL*) previewItemURL
{
return self.URL;
}
- (NSString*) previewItemTitle
{
return self.name;
}
@end
Простой. Теперь представьте следующую реализацию источника данных QLPreviewPanel:
AlbumViewController.m
- (NSInteger) numberOfPreviewItemsInPreviewPanel: (QLPreviewPanel*) panel
{
// 'currentAlbum' property contains the currently-represented MLMediaGroup object.
return self.currentAlbum.count;
}
- (id<QLPreviewItem>) previewPanel: (QLPreviewPanel*) panel previewItemAtIndex: (NSInteger) index
{
return self.currentAlbum[index];
}
Все идет нормально. Но если мы посмотрим на немногочисленную и обычно вводящую в заблуждение документацию Apple, мы можем обнаружить следующие важные детали:
URL
Расположение медиа-объекта. (только для чтения)
Это свойство предоставляется как URL с ограничением безопасности. Чтобы получить доступ к файлу, на который ссылается этот URL-адрес, вызывающий должен вызватьstartAccessingSecurityScopedResource
до иstopAccessingSecurityScopedResource
после использования URL-адреса для доступа к файлу.
Итак, очевидно, что доступ к ресурсу должен быть ограничен парой вызовов _6 _ / _ 7_.
Вопрос в том, где мне разместить эти вызовы с учетом текущего QLPreviewPanelDataSource
определения протокола? Это зависит от QLPreviewPanel, чтобы получить доступ к ресурсу, а не к моему коду, но, к сожалению, я вряд ли когда-нибудь поверю, что Apple обновила QL для работы в среде «песочницы».
Как действовать в случаях, когда startAccessingSecurityScopedResource
вызов возвращает NO
, сообщая об отсутствии доступа?
Похоже, когда вы пытаетесь startAccessingSecurityScopedResource
использовать URL-адрес, к которому уже осуществляется доступ, вы получаете флаг ошибки при возврате. Мол, все ок, но выдает ошибку. Похоже, что эти вызовы start / stop ... должны быть точно спарены, и даже сбалансированное вложение запрещено. Итак, как отличить две возможности, когда вы получаете NO
при возврате: URL-адрес с областью безопасности, к которому уже осуществляется доступ, и URL-адрес с областью безопасности, который не удалось "разрешить"?
Экспериментально подтвержденный факт, что ваше приложение может получить доступ только к ограниченному количеству URL-адресов с ограниченным уровнем безопасности (вы можете взять около 1500 URL-адресов, прежде чем оно автоматически перестанет работать). Итак, как мне правильно отказаться от доступа к URL-адресам в области безопасности после того, как я передал их в QLPreviewPanel? Когда наступит подходящий момент? Мне кажется, что это частная деталь реализации класса QLPreviewPanel, и я не могу делать никаких предположений относительно его внутренней работы.