首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在沙箱中打开相关文件有没有NSFileCoordinator的替代方案?

在沙箱中打开相关文件有没有NSFileCoordinator的替代方案?
EN

Stack Overflow用户
提问于 2020-01-03 00:44:26
回答 1查看 502关注 0票数 2

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

虽然答案中没有涉及,但苹果文档告诉我们,要访问“相关文件”,我们必须使用NSFileCoordinator for access (ref)。

这对我的需求来说有点繁重,而且带来了架构问题,因为实际的文件访问是在我的后端代码中,远离Apple库设施的范围。如果可以的话,我不想使用NSFileCoordinator来获取相关文件的内容。我也不想要求我的用户手动识别sidecar文件(如果没有其他东西,这对于批处理来说将是一个糟糕的工作流)。我只想告诉沙盒“没关系,这个应用程序可以在用户选择File.ABC之后打开某某相关的File.XYZ”。

对于正常的文件访问,这不是问题:使用open a file that's been previously selected from an Open panelstd::ifstream似乎可以在应用程序实例的剩余生命周期中工作。

但打开一个“相关文件”似乎更加有限。

在我的应用程序的plist中添加了一个NSIsRelatedItemType (如链接的答案所示),我可以在前端做的最小的事情是什么,大概是在打开“主”/requested文件之后,这样我以后也可以使用std::ifstream打开相关的sidecar文件?关于这个主题的文档似乎有些稀疏…

也许我最好的办法是执行一次性提示,让用户授权访问封装目录,并将生成的授权保存为应用程序范围的书签(ref),但这并不像我希望的那样透明。对于用户来说,面对这样的请求也可能有点“可怕”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-03 22:49:25

不需要,因为操作系统实际上可能会将文件复制到不同的位置,以便为您提供对它的访问权限,因此您必须使用NSFileCoordinator

但并不是所有的都失去了!这里有一个技巧:即使你的后端代码被设计成可移植的,如果你在Xcode中将文件读取源代码设置为"Objective-C++ .cpp“,你可以直接使用基础特性(#import <Foundation/Foundation.h>)。

因此,无论您当前在何处实例化和读取std::ifstream,都应该有一个#if defined(PLATFORM_MAC_OS_X) (或其他任何东西),并在其中用NSFileCoordinator代码包装您的文件读取。

上图:

代码语言:javascript
复制
#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

之后的版本:

代码语言:javascript
复制
#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是同步调用的,所以您也不必担心竞争条件(可能只是一些额外的延迟)。唯一的代价是一些特定于平台的泄漏,但至少它隐藏在预处理器指令中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59566959

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档