gpt4 book ai didi

c++ - 有没有NSFileCoordinator的替代方案,可以在沙箱中打开相关文件?

转载 作者:行者123 更新时间:2023-12-01 14:58:15 27 4
gpt4 key购买 nike

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

尽管此处的答案未涵盖其中,但Apple文档告诉我们,要访问“相关文件”,我们必须使用NSFileCoordinator进行访问(ref)。

由于实际的文件访问位于我的后端代码中,而Apple库设施无法访问,因此这对于我的需求来说有点沉重,并且造成了体系结构问题。如果可以,我不需要使用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),但这又不是我想要的那么透明。用户面对这样的请求可能也有些“吓人”。

最佳答案

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

但是,一切都不会丢失!有一个技巧:即使您的后端代码被设计为可移植的,但是如果您在Xcode中将读取文件的.cpp设置为“Objective-C++源代码”,则可以在那里使用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是同步调用的,因此您也不必担心竞争条件(可能只是一点额外的延迟)。唯一的代价是特定于平台的泄漏,但至少隐藏在预处理器指令中。

关于c++ - 有没有NSFileCoordinator的替代方案,可以在沙箱中打开相关文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59566959/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com