4

当尝试组合快速查看预览面板和安全范围的 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 数据源实现:

相册视图控制器.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 所引用的文件,调用者必须在使用该 URL 访问该文件startAccessingSecurityScopedResource之前和之后调用。stopAccessingSecurityScopedResource

因此,很明显,对资源的访问必须用startAccessingSecurityScopedResource/stopAccessingSecurityScopedResource调用对括起来。

问题是在给定当前QLPreviewPanelDataSource协议定义的情况下我应该把这些调用放在哪里?访问资源取决于 QLPreviewPanel,而不是我的代码,但不幸的是,我几乎不会相信 Apple 更新了 QL 以在沙盒环境中运行。

startAccessingSecurityScopedResource当呼叫返回时,我如何处理这些情况,NO说明无法获得访问权限?

似乎当您尝试startAccessingSecurityScopedResource访问已被访问的 URL 时,您会在返回时获得失败标志。就像,一切都很好,但是你得到一个错误标志。似乎这些开始/停止......调用必须精确配对,甚至禁止平衡嵌套。那么,当您获得返回时如何区分这两种可能性NO:已被访问的安全范围 URL 和未能“解析”的安全范围 URL?

这是一个经过实验证明的事实,您的应用程序只能访问有限数量的安全范围 URL(在它静默停止工作之前,您可以获取大约 1500 个 URL)。那么,在将安全范围的 URL 传递给 QLPreviewPanel 之后,我应该如何正确放弃对它们的访问?什么时候这样做合适?在我看来,它是 QLPreviewPanel 类的私有实现细节,我无法对其内部工作做出任何假设。

4

1 回答 1

-1

您可以使用:

- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
    [bookmarkURL startAccessingSecurityScopedResource];
    //... Your code

}

- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
    //... Your Code
    [bookmarkURL stopAccessingSecurityScopedResource];
}
于 2015-09-10T08:33:17.367 回答