macOS Apple帮助创作-锚点

时间:2018-12-05 17:30:27

标签: macos appkit nsalert apple-help

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

  

“锚使您可以唯一地识别帮助书中的主题。何时   用户点击指向锚点的链接,帮助查看器加载页面   包含锚点。 ...您也可以使用锚点加载   通过调用应用程序中的锚定页面   NSHelpManager方法openHelpAnchor:inBook:...“

Apple的示例:<a name="ArrivalTimesUsingStopID"></a>

在我的Apple中,我有一个NSAlert,其中包含以下代码来显示帮助按钮,以便在单击该按钮时可以打开指定的定位字符串。

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

运行代码会显示帮助按钮,并且Mac帮助会打开,但是会出现一条错误消息,指出找不到指定的内容。不确定为什么锚点不起作用,因为如果我进入“帮助”菜单并从那里打开它,我可以访问

此外,Apple的文档指出:

  

NSAlert,SFChooseIdentityPanel,SFCertificatePanel类提供   对话框的帮助按钮。显示这样的帮助按钮并将其链接到   您的帮助书中的锚点,请使用setShowsHelp方法:   setHelpAnchor:在这些类中。

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

  

-setShowsHelp:YES将帮助按钮添加到警报面板。当按下帮助按钮时,将首先咨询该代表。如果代表   不实现alertShowHelp:或返回NO,则-[NSHelpManager   使用零本书和锚点调用openHelpAnchor:inBook:]   由-setHelpAnchor:指定(如果有)。如果出现异常,将引发   委托返回NO,并且没有帮助锚集。

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

我还了解到,每次更新Apple帮助手册HTML文档时,都需要创建.helpindex文件。我正在使用developer.apple.com上“其他Xcode工具”中的“帮助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)

使用nil作为inBook参数也不起作用:

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

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我现在不确定这是不是答案,但这是答案,似乎是可行的方法。我无法在“警报”中使helpAnchor正常工作,但是使用帮助委托,下面概述的方法有效。

我一开始尝试将帮助书打开到一个简单的锚点。我敢肯定,过去曾经使用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>附加到我的URL:

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时,肯定会打开帮助中的锚点;他们将打开正确的锚点位置。

这需要找到特定的帮助手册和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. 通过将方案从NSURLComponents更改为NSURL,并在file中添加我们的助手,使用help界面对fragment进行突变。
  4. 最后,打开新创建的URL

它并不漂亮,但至少在10.15以下的非沙盒装macOS App中,它确实是有效和安全的。

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

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

- (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];

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

答案 1 :(得分: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文件夹中。我发现删除“应用程序”文件夹中的副本通常可以帮助打开打开“帮助手册”时不使macOS感到困惑。我还发现它可以打开旧版本的帮助书,因此,最好在调试帮助书时确保Mac上只有一次应用程序副本。

但是除此之外,根据您显示“帮助”按钮的方式,它们应该只用锚定字符串和几行代码就可以正常打开!