从Launch Services中隐藏NSDocument子类

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

我有一对基本上是双胞胎的应用程序-一个是客户端,另一个是服务器。它们共享许多相同的代码,并且都使用相同的NSDocument子类来实现它们共享的文档格式。客户端应用程序具有用户界面,并允许用户直观地处理文档,但是服务器应用程序则没有(尽管它确实作为常规应用程序运行,而不是作为守护程序运行),但其设计目的是在看不见的情况下运行。

问题是,将文档放在其图标上时会触发服务器应用程序。如果服务器应用程序正在运行而客户端应用程序未运行,则服务器应用程序也会被触发,并且用户双击文档。在那种情况下,我要启动的服务是启动客户端应用程序并打开文档,而是尝试使用服务器应用程序打开文档。我已经自定义了NSApplicationDelegate application:openFile:方法,以便服务器应用在这种情况下拒绝实际打开文档,但是我想要的是让NSApplicationDelegate不使用文档打开事件来调用它。用户感到困惑,因为他们希望双击文档以打开客户端应用程序,而不管服务器应用程序是否正在运行。

Apple的Core Foundation Keys文档似乎表明执行此操作的方法是使用LSHandlerRank属性。

https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-SW1

对于客户端应用程序,我将其设置为“所有者”。

<key>LSHandlerRank</key>
<string>Owner</string>

对于服务器应用程序,我将其设置为“无”。

<key>LSHandlerRank</key>
<string>None</string>

不幸的是,这没有效果。我仍然可以将文档放在服务器应用程序图标上,或者如果客户端应用程序未在运行,请双击文档以使服务器应用程序前进。

我认为可能很有希望的另一个属性是CFBundleTypeRole。客户端应用程序的plist将此设置为“编辑器”。

<key>CFBundleTypeRole</key>
<string>Editor</string>

此属性的文档确实很少,但是它确实说“无”是一个选择。因此,我在服务器应用程序plist中尝试了该操作,然后无法再以编程方式打开NSDocument文件。另一方面,将文档放在服务器应用程序图标still上会使该图标点亮,因此Launch Services显然仍然认为服务器应用程序可以处理此类文件。

总而言之,我需要对plist进行一些更改,以便我仍然可以以编程方式使用与NSDocument子类关联的文件,但是我不希望Launch Services知道我的(服务器)应用程序可以使用这些文档。这可能吗?

----跟随Peter Hosey的回答----

感谢您的回答。我不知道lsregister shell命令,它看起来非常方便。转储在我的计算机上产生46兆字节的数据!

但是,我很确定这不是缓存问题。尽管我的计算机具有服务器应用程序的多个副本,但是此问题是由客户发现的。他只有该应用程序的一个副本,而且只有很短的时间。一年多来我一直没有更改plist的内容,因此在他的系统上没有任何可缓存的内容。

[您建议不使用Launch Services,但我并没有明确表示自己,我没有利用它,也不希望Launch Services打开我的文档(至少不使用我应用的服务器版本)。正在通过内部TCP / IP服务器使用openDocumenWithContentsOfURL来打开文档,如下所示:

[sharedDocumentController openDocumentWithContentsOfURL:databaseURL display:openWindows error:&err];

openDocumenWithContentsOfURL方法似乎要求为文档类型设置plist。我的问题是,这还告诉Finder该应用程序可以处理我不想要的这种类型的文档。因此,我正在寻找可以在应用程序中使用NSDocument的某种方式,但不要将其公开给Finder(因此我认为不应该将其公开给Launch Services)。也许那是不可能的。

是否有某种方法可以在没有URL的情况下打开文档,因此扩展名是什么或plist的设置如何都没有关系?我在NSDocumentController类中没有看到任何这样的文档化方法。在我看来,并且测试似乎证实,NSDocument类依赖于plist将文件扩展名链接到NSDocument子类。

如果有一种方法可以更改plist来执行此操作,那么我肯定会需要使用lsregister来清除缓存以进行测试:)

macos cocoa info.plist
1个回答
0
投票

使用LS的挑战之一是缓存失效(众所周知,这是计算机科学中最难解决的两个问题之一,同时还涉及事物的命名和一个错误的错误)。 LS出于性能原因希望缓存所有内容,因此,当您更改某些内容时,确保从LS的数据库中清除旧信息就变得很重要。

首先要检查的是您拥有多少服务器应用程序副本。如果您曾经将其复制到build products文件夹之外,则该旧副本可能是LS试图用来处理文档的副本。

第二件事要检查的是服务器应用程序LS认为您拥有哪些副本,以及它认为它们可以处理的内容。

这两种方法都使用lsregister -dump。 lsregister被分散在/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister中,其转储将为您提供有关注册了哪些类型(UTI),注册了哪些应用程序包的大量信息。 (包括在不同位置具有不同功能的不同版本),服务等。

lsregister -help会告诉您其他选项,其中一些选项可能有助于从LS的数据库中淘汰过时/无用的记录。

我可能会避免使用LS。也许将类型导入服务器应用程序的Info.plist中,但不要将其列为文档类型,也不要使用客户端中的LS通过服务器应用程序打开文档。

相反,使用NSAppleEventDescriptor创建您自己的Open Documents事件,然后使用AESendMessage将其发送到服务器应用程序。事件类别为kCoreEventClass,事件ID为kAEOpenDocuments。目标描述符应该是typeApplicationBundleID类型的NSAppleEventDescriptor,其中包含服务器应用程序的捆绑软件ID作为字符串。

将事件的keyDirectObject关键字参数设置为至少一个typeFileURL描述符的列表描述符,该描述符包含要打开的文档的URL(也表示为字符串)。

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