当人们试图将Quick Look预览面板和安全范围的URL组合在一起时,Cocoa中出现选择不当,不可组合的抽象存在问题。
我有一个具体的例子:
想象一下,我们正在尝试从MediaLibrary中显示某些对象的预览(MediaLibrary.framework允许应用程序通过方便的API浏览iPhoto,Aperture ...和照片库)。
最简单直接的方法是调整'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
。
因此,很明显,对资源的访问必须使用startAccessingSecurityScopedResource
/ stopAccessingSecurityScopedResource
个呼叫对进行括号。
问题是在给定当前QLPreviewPanelDataSource
协议定义的情况下,我应该将这些调用放在哪里?由QLPreviewPanel来访问资源,而不是我的代码,但遗憾的是我几乎不会相信Apple更新了QL以在沙盒方面运行。
如果startAccessingSecurityScopedResource
调用返回NO
,说明无法获取访问权限,我该如何处理这些案例?
似乎当你在已经被访问的URL上尝试startAccessingSecurityScopedResource
时,你会在返回时获得失败标志。就像,一切都很好,但你得到一个错误标志。似乎这些开始/停止......呼叫必须精确配对,甚至禁止平衡嵌套。 那么,如何在返回NO
时区分这两种可能性:一个已经被访问的安全范围的URL和一个未能“解析”的安全范围的URL?
这是一个经过实验验证的事实,您的应用程序只能访问有限数量的安全范围的URL(您可以在静默停止工作之前获取大约~1500个URL)。那么,在我将它们传递给QLPreviewPanel之后,我应该如何正确地放弃对安全范围URL的访问?在适当的时候这样做?在我看来,它是QLPreviewPanel类的私有实现细节,我不能对其内部工作做出任何假设。