如何正确实现QLPreviewPanel数据源,同时考虑安全范围的URL?

时间:2015-05-12 15:41:35

标签: objective-c cocoa sandbox quicklook security-scoped-bookmarks

当人们试图将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类的私有实现细节,我不能对其内部工作做出任何假设。

0 个答案:

没有答案