Macos 从启动服务中隐藏NSDocument子类

Macos 从启动服务中隐藏NSDocument子类,macos,cocoa,info.plist,Macos,Cocoa,Info.plist,我有一对基本上是双胞胎的应用程序——一个是客户端,另一个是服务器。它们共享许多相同的代码,并且都使用相同的NSDocument子类来实现它们共享的文档格式。客户端应用程序有一个用户界面,允许用户直观地处理文档,但服务器应用程序没有(尽管它确实作为常规应用程序运行,而不是作为守护程序运行),它被设计为以不可见的方式运行 问题在于,当文档被放到服务器应用程序的图标上时,服务器应用程序会被触发。如果服务器应用正在运行,而客户端应用未运行,并且用户双击文档,也会触发服务器应用。在这种情况下,我希望Lau

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

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

苹果的核心基础密钥文档似乎表明,使用LHANDLRANK属性的方法是这样的。

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

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

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


如果有办法改变plist来做到这一点,那么我肯定需要使用lsregister清除缓存来测试:)

使用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是
kaeopendictions
。目标描述符应该是类型为
typeApplicationBundleID
的NSAppleEventDescriptor,以字符串形式包含服务器应用程序的捆绑ID


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

Ohhh,因此您没有使用启动服务(或Apple事件)将“文档”发送到服务器,但是服务器通过使用NSDocumentController“打开”文档来处理请求(通过其他方式接收)。您会发现,NSDocumentController需要Info.plist中的文档类型,以便知道要使用哪个NSDocument子类

这是您可以在NSDocumentController子类中重写的内容:

  • -typeForContentsOfURL:错误:
    :给定URL,返回一个字符串,指示该URL引用的文档类型。默认行为通过在其标记中查找具有URL的
    pathExtension
    的类型来实现这一点。根据您希望的严格程度,您可以执行类似的检查,如果类型名称是客户机合理发送的文档,则只返回类型名称;或者您可以懒惰,只返回常量字符串(如果您的服务器只处理一种类型的“文档”)
  • -documentClassForType:
    :给定文档类型名称,返回要实例化的NSDocument子类以管理该类型的文档。只要您只处理一种类型,因此只有一个子类NSDocument,您就可以无条件返回NSDocument子类;如果您有多个这样的子类,或者希望规划将来可能使用的子类,请将类型名与每个已知的类型名进行比较,并返回相应的子类
  • -displayNameForType:
    :给定文档类型名称
    <key>LSHandlerRank</key>
    <string>Owner</string>
    
    <key>LSHandlerRank</key>
    <string>None</string>
    
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    
    [sharedDocumentController openDocumentWithContentsOfURL:databaseURL display:openWindows error:&err];