gpt4 book ai didi

macos - 从启动服务中隐藏NSDocument子类

转载 作者:行者123 更新时间:2023-12-03 17:00:56 25 4
gpt4 key购买 nike

我有一对基本上是双胞胎的应用程序-一个是客户端,另一个是服务器。它们共享许多相同的代码,并且都使用相同的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文件。另一方面,将文档放在服务器应用程序图标上仍然会使该图标点亮,因此Launch Services显然仍然认为服务器应用程序可以处理这种类型的文件。

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

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

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

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

您建议不要使用Launch Services,但我并没有明确表示自己,我没有利用它,也不希望Launch Services打开我的文档(至少不使用我的应用程序的服务器版本)。实际上,我已经成功修改了该应用程序,因此,如果Launch Services确实请求服务器应用程序打开文档,它将忽略此请求。通过使用 openDocumenWithContentsOfURL的内部TCP / IP服务器可以完成文档的打开,如下所示:

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


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

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

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

最佳答案

哦,所以您没有使用Launch Services(或Apple Events)将“文档”发送到服务器,但是服务器通过使用NSDocumentController“打开”“文档”来处理请求(通过其他方式接收)。而且您发现的是NSDocumentController需要Info.plist中的文档类型才能知道要使用哪个NSDocument子类。

您可以在NSDocumentController子类中覆盖以下内容:


-typeForContentsOfURL:error::给定URL,返回一个字符串,指示URL引用的文档类型。默认行为是通过在其标签中查找具有URL pathExtension的类型来实现的。根据您想要的严格程度,您可以执行类似的检查,并且仅在类型文件是由客户合理地发送的文档时才返回类型名,或者您可能很懒而仅返回常量字符串(如果服务器仅处理一种类型) “文档”)。
-documentClassForType::给定文档类型名称,返回NSDocument子类以实例化以管理该类型的文档。只要您只处理一种类型,因此只有一个NSDocument子类,就可以无条件返回NSDocument子类。如果您有多个这样的子类,或者想为将来做一个规划,请将类型名称与每个已知的类型名称进行比较,然后返回适当的子类。
-displayNameForType::给定文档类型名称,返回包含该类型的用户可表示名称的本地化字符串(例如,英语的“网页”,而不是“ public.html”)。您的情况可能不需要。
-documentClassNames:返回一个NSDocument子类名称的数组,可以实例化这些子类来管理应用程序可以处理的文档。出于您的目的可能不是必需的,但是默认实现会查询您的Info.plist。
-defaultType:用于新文档的文档类型的名称(如newDocument:操作中所示)。如果您不是从服务器创建新文档,则可能不相关,但是默认实现会查询您的Info.plist(它返回您已声明自己为编辑器的第一种类型)。


通过在NSDocumentController子类中覆盖这些方法,文档控制器将不再查询Info.plist,并且您可以删除与LS不想了解的文档类型有关的Info.plist信息。

如果您尚未使用NSDocumentController子类,则需要创建一个子类,并在程序的早期调用[MyDocumentController sharedDocumentController](您可能甚至需要在main中进行操作才能在笔尖加载之前进行操作;已经有一段时间了) (因为我已经研究了实例化文档控制器的时间和位置)。发送该消息到您的子类将确保从该子类创建文档控制器,从而具有您在该子类中实现的行为。

关于macos - 从启动服务中隐藏NSDocument子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61118149/

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