4

我正在尝试为我准备发布的 macOS 应用程序制作 Apple 帮助手册。但是,我正在尝试使锚点在我的 HTML 中工作。按照苹果的定义:

“锚点允许您唯一标识帮助手册中的主题。当用户点击指向锚点的链接时,帮助查看器会加载包含锚点的页面。......您还可以使用锚点从应用程序中加载锚定页面:调用 NSHelpManager 方法 openHelpAnchor:inBook: ..."

苹果的例子:<a name="ArrivalTimesUsingStopID"></a>

在我的 Apple 中,我有一个 NSAlert,它具有以下代码来显示帮助按钮,以便当您单击它时,它会打开指定的锚字符串。

alert.showsHelp = true
alert.helpAnchor = NSHelpManager.AnchorName(stringLiteral: "ArrivalTimesUsingStopID")

运行代码确实会显示帮助按钮,并且 Mac 帮助确实会打开,但是会出现一个错误,指出找不到指定的内容。不知道为什么锚不工作,因为如果我转到帮助菜单并从那里打开它,我可以访问帮助手册。

此外,Apple 的文件指出:

NSAlert、SFChoseIdentityPanel、SFCertificatePanel 类为对话框提供帮助按钮。要显示此类帮助按钮并将其链接到帮助手册中的锚点,请在这些类中使用方法 setShowsHelp: 和 setHelpAnchor:。

以及这些属性的文档NSAlert状态:

-setShowsHelp:YES 向警报面板添加帮助按钮。当按下帮助按钮时,首先咨询代表。如果委托没有实现 alertShowHelp: 或返回 NO,则 -[NSHelpManager openHelpAnchor:inBook:] 使用 nil book 和 -setHelpAnchor: 指定的锚点调用,如果有的话。如果委托返回 NO 并且没有设置帮助锚点,则会引发异常。

...所以我知道我正在正确使用这两个。

我还了解每次更新 Apple 帮助手册 HTML 文档时都需要创建一个 .helpindex 文件。我正在使用 developer.apple.com 上的 Additional Xcode Tools 中的“Help Indexer.app”。我确保:

  • 我设置了索引所有锚点的选项。
  • 任何带有锚点的 HTML 页面都<meta name="ROBOTS" content="ANCHORS">在标题中,因此锚点会被编入索引。
  • 我的 Apple 帮助书 plist 文件正确指向由“Help Indexer.app”创建的 .helpindex 文件。

但即使有了所有这些,我也无法将 Apple 帮助书打开到正确的锚点,甚至无法打开 Apple 帮助书的标题页。

我已阅读 https://developer.apple.com/library/archive/documentation/Carbon/Conceptual/ProvidingUserAssitAppleHelp/user_help_intro/user_assistance_intro.html#//apple_ref/doc/uid/TP30000903-CH204-CHDIDJFE

从封面到封面多次,我无法在网上找到解决方案或任何地方。

我也尝试过手动打开它,但它只是打开相同的错误,说无法使用以下代码找到指定的内容:

let bookName = Bundle.main.object(forInfoDictionaryKey: "CFBundleHelpBookName") as! String
NSHelpManager.shared.openHelpAnchor("ArrivalTimesUsingStopID", inBook: bookName)

使用nilinBook 参数也不起作用:

NSHelpManager.shared.openHelpAnchor("ArrivalTimesUsingStopID", inBook: nil)

有任何想法吗?

4

2 回答 2

1

我不确定这是否是此时的答案,但这是一个答案,而且似乎可以解决问题。我无法让helpAnchorAlert 工作,但使用帮助委托,下面概述的方法有效。

我开始我的一天,试图打开一个简单的锚点帮助手册。我确信这NSHelpManager在过去使用过,但在最新版本的操作系统中似乎没有。

在打开我正在开发的应用程序的帮助手册时观看控制台导致以下结果:

Opening URL help:openbook=%22com.ClueTrust.Cartographica.help*1.5.2d1%22 with application <FSNode 0x6000006a1b40> { isDir = y, path = '/System/Library/CoreServices/HelpViewer.app' }

使用打开我的锚点NSHelpManager导致:

Opening URL help:anchor=SpatialJoinOperation%20bookID=%22com.ClueTrust.Cartographica.help%22%20appID=%22com.ClueTrust.Cartographica%22 with application <FSNode 0x6000006a8260> { isDir = y, path = '/System/Library/CoreServices/HelpViewer.app' }

而且,它并没有导致我的锚打开。

我尝试将 附加*<version>到我的网址:

Opening URL help:anchor=SpatialJoinOperation%20bookID=%22com.ClueTrust.Cartographica.help*1.5.2d1%22%20appID=%22com.ClueTrust.Cartographica%22 with application <FSNode 0x600000682c20> { isDir = y, path = '/System/Library/CoreServices/HelpViewer.app'

但是,深入查看控制台,我注意到这肯定会触发网络请求并且unsupported URL会返回。

我不清楚是否help:anchor=...不再起作用,但我确实找到了一种相对简单但令人讨厌的解决问题的方法。

当使用help:格式类似于file:URL 并包含锚点的 URL 时,帮助中的锚点肯定会被打开;它们将打开到正确的锚点位置。

这需要找到特定的帮助手册和 HTML 文件,以便您可以准确指定打开的位置。

    NSURL *helpBookURL = [NSBundle.mainBundle URLForResource:@"Cartographica" withExtension:@"help"];
    NSBundle *helpBundle = [NSBundle bundleWithURL:helpBookURL];
    NSURL *helpPageURL = [helpBundle URLForResource:@"Spatial_Join" withExtension:@"html"];
    NSURLComponents *urlParts = [NSURLComponents componentsWithURL:helpPageURL resolvingAgainstBaseURL:NO];
    urlParts.scheme=@"help";
    urlParts.fragment=@"SpatialJoinOperation";
    NSURL *finalHelpURL = urlParts.URL;
    [NSWorkspace.sharedWorkspace openURL:finalHelpURL];

基本上:

  1. 获取帮助手册的 URL(需要以从资源路径获取它的方式执行此操作,因此我们使用的是 NSBundle)
  2. 根据先验知识找到包含引用的页面(在本例Spatial_Join.html中是我们的文件名,因此我们让捆绑包按名称和扩展名查找它。
  3. 通过将方案从to更改为并将我们的 achor 添加NSURLComponents到.NSURLfilehelpfragment
  4. 最后,打开新建的 URL

它并不漂亮,但它似乎确实有效且安全,至少在 10.15 以下的非沙盒 macOS 应用程序中是这样。

请注意,我可以在这里对帮助书名称做出一些假设,但出于说明目的,这似乎更清楚,并且由于资源的工作方式,不清楚这些关于名称的假设是否适用于所有情况。

我的最终结果是这个辅助方法:

- (void)openHelpPage:(NSString*)pageName anchor:(NSString  * _Nullable)anchor bookName:(NSString * _Nullable)bookName
{
    NSURL *helpBookURL = [NSBundle.mainBundle URLForResource:bookName withExtension:@"help"];
    NSBundle *helpBundle = [NSBundle bundleWithURL:helpBookURL];
    NSURL *helpPageURL = [helpBundle URLForResource:pageName withExtension:@"html"];
    NSURLComponents *urlParts = [NSURLComponents componentsWithURL:helpPageURL resolvingAgainstBaseURL:NO];
    urlParts.scheme=@"help";
    if (anchor)
        urlParts.fragment=anchor;
    NSURL *finalHelpURL = urlParts.URL;
    [NSWorkspace.sharedWorkspace openURL:finalHelpURL];
}

调用站点语法是:

// to specific anchor on a page
[self openHelpPage: @"Spatial_Join" anchor: @"SpatialJoinOperation" helpBook: nil];
// to specific page
[self openHelpPage: @"Spatial_Join" anchor: nil helpBook: nil];

我尝试[NSBundle bundleWithIdentifier:]使用帮助包 ID 获取帮助包,但返回 nil。但是,[NSBundle URLForResource:withExtension]将为 提供一个nil参数resourceName并获取与扩展名匹配的第一个项目。在我的情况下(我相信很多)只有一个help资源,因此这允许一种不需要了解应用程序帮助书名称的方法。

于 2020-08-09T12:16:13.440 回答
0

我终于能够在沙盒应用程序中使用它。

如果您直接使用帮助按钮,则可以使用以下内容:

@IBAction func helpButtonAction(_ sender: Any)
{
    if  let bookName = Bundle.main.object(forInfoDictionaryKey: "CFBundleHelpBookName") as? String {
        NSHelpManager.shared.openHelpAnchor("MY_ANCHOR_HERE", inBook: bookName)
    }
}

如果您使用的是NSAlert(),则可以通过以下方式将其帮助按钮与锚点一起使用:

let alert = NSAlert()
...
alert.showsHelp = true
alert.helpAnchor = NSHelpManager.AnchorName("MY_ANCHOR_HERE")

我通过艰难的方式学到了一些东西:

  1. 确保帮助手册的 HTML 页面具有正确的锚点设置:

<meta name="robots" content="anchors">在该<head>部分以及适当的标题标签中:

<a name="MY_ANCHOR_HERE"></a>在你的<body>部分。

  1. 确保您使用“Help Indexer.app”来索引您的帮助手册。我发现除非您使用此应用程序索引您的帮助手册,否则它将无法正常工作。这个应用程序可以从developer.apple.com更多下载下下载。他们通常会在每次 Xcode 更新时发布一个新版本。您要查找“其他工具”,特定的索引器应用程序将位于

    其他工具 > 实用程序 > 帮助 Indexer.app

  2. 此外,macOS 不喜欢你有多个帮助书。这意味着,您的 Mac 上的应用程序的多个副本,无论它们位于何处。这可能在您的 Debug 文件夹和您的 Application 文件夹中作为您最常用的位置。我发现删除我的 Applications 文件夹中的副本通常有助于 macOS 在打开帮助手册时不会感到困惑。我还发现它可以打开旧版本的帮助手册,因此最好确保在调试帮助手册时您的 Mac 上只有一次应用程序副本。

但除此之外,它们应该只需一个锚字符串和几行代码就可以很好地打开,具体取决于您显示帮助按钮的方式!

于 2020-09-06T18:44:40.953 回答