是否有NSFileCoordinator的替代品,用于在沙箱中打开相关文件?

问题描述 投票:1回答:1

这是Access sidecar files in a Mac sandboxed app的后续行动。

尽管这里的答案没有涵盖,但是Apple文档告诉我们,要访问“相关文件”,我们必须使用NSFileCoordinator进行访问(ref)。

这对于我的需求来说有点沉重,并且造成了体系结构问题,因为实际的文件访问位于我的后端代码中,而不是苹果图书馆的设施。如果可以帮助,我不需要使用NSFileCoordinator来获取相关文件的内容。我也不想要求用户手动标识sidecar文件(如果没有其他要求,这对于批处理而言将是一个糟糕的工作流程)。我只想告诉沙盒“没关系,在用户选择File.ABC之后,此应用程序可以打开与之相关的File.XYZ”。

对于普通文件访问,这不是问题:在应用程序实例的整个生命周期中,使用std::ifstreamopen a file that's been previously selected from an Open panel似乎都可以使用。

但是打开“相关文件”似乎更受限制。

已在我的应用程序的plist中添加了NSIsRelatedItemType(如链接的答案所示),我大概在打开“主要” /请求的文件后立即可以在前端执行的最小操作是,以后还可以使用std::ifstream打开相关的sidecar文件吗?文档在这个主题上似乎有点稀疏...

也许我最好的选择是执行一次提示,提示用户授权访问封装目录,并将产生的权利保存为应用程序作用域的书签(ref),但这又不像我那么透明想要。用户面对这样的请求可能也有些“吓人”。

c++ xcode macos sandbox sidecar
1个回答
0
投票

否,因为操作系统会[潜在地]实际上将文件复制到其他位置以便向您提供对其的访问权限,所以您必须使用NSFileCoordinator

但是一切都不会丢失!有一个技巧:即使您的后端代码被设计为可移植的,但是如果您在Xcode中将文件读取.cpp设置为“ Objective-C ++ Source”,则可以使用Foundation功能(#import <Foundation/Foundation.h>)那里。

因此,无论您当前在何处实例化并从std::ifstream读取数据,都需要一个#if defined(PLATFORM_MAC_OS_X)(或其他内容),然后在其中放入NSFileCoordinator代码来包装文件读取的内容。

上方:

#ifdef PLATFORM_MAC_OS_X
#import <Foundation/Foundation.h>

@interface SidecarPresenter : NSObject<NSFilePresenter>
@property(readwrite, copy) NSURL* presentedItemURL;
@property(readwrite, copy) NSURL* primaryPresentedItemURL;
@property(readwrite, assign) NSOperationQueue* presentedItemOperationQueue;

-(instancetype)initWithImageUrl:(NSURL*)imageUrl andSidecarExtension:(NSString*)newExt;
@end

@implementation SidecarPresenter

- (instancetype)initWithImageUrl:(NSURL*)imageUrl andSidecarExtension:(NSString*)newExt
{
    self = [super init];

    if (self)
    {
        [self setPrimaryPresentedItemURL:imageURL];
        [self setPresentedItemURL:[[imageUrl URLByDeletingPathExtension] URLByAppendingPathExtension:newExt]];
        [self setPresentedItemOperationQueue:[NSOperationQueue mainQueue]];
    }

    return self;
}

- (void)dealloc
{
    [_primaryPresentedItemURL release];
    [_presentedItemURL release];

    [super dealloc];
}

@end
#endif

以及以后:

#ifdef PLATFORM_MAC_OS_X
SidecarPresenter* presenter = [SidecarPresenter alloc];
[presenter initWithImageUrl:[NSURL fileURLWithPath:documentFilename]
        andSidecarExtension:sidecarExtension]];
[presenter autorelease];

[NSFileCoordinator addFilePresenter:presenter];
NSFileCoordinator* coordinator = [[[NSFileCoordinator alloc] initWithFilePresenter:presenter] autorelease];

NSError* error = nil;
[coordinator coordinateReadingItemAtURL:presenter.presentedItemURL
                                options:NSFileCoordinatorReadingWithoutChanges
                                  error:&error
                             byAccessor:^(NSURL* newURL)
{
   std::ifstream strm([newURL fileSystemRepresentation]);
   foo(strm);
}];

[NSFileCoordinator removeFilePresenter:presenter];

#else
std::ifstream strm(documentFilename);
foo(strm);
#endif

这样,在后端和前端之间就不会出现来回乒乓的现象。而且lambda是同步调用的,因此您也不必担心竞争状况(可能只是一点额外的延迟)。唯一的代价是特定于平台的泄漏,但至少隐藏在预处理器指令中。

© www.soinside.com 2019 - 2024. All rights reserved.