I'm trying to make an Apple Help book for my macOS app that I'm ready to release. However, I am trying to make anchors work in my HTML. By Apple's definition:
"Anchors allow you to uniquely identify topics in your help book. When a user follows a link to an anchor, Help Viewer loads the page containing the anchor. ... You can also use anchors to load an anchored page from within your application by calling the the NSHelpManager method openHelpAnchor:inBook: ..."
Example from Apple: <a name="ArrivalTimesUsingStopID"></a>
In my Apple, I have an NSAlert which has the following code to display the help button so that when you click on it, it opens the specified anchor string.
alert.showsHelp = true
alert.helpAnchor = NSHelpManager.AnchorName(stringLiteral: "ArrivalTimesUsingStopID")
Running the code does display the help button and Mac Help does open, but to an error saying that the specified content cannot be found. Not sure why the anchors aren't working because I can access the Help Book if I go to the Help menu and open it from there.
Furthermore, Apple's document states:
The NSAlert, SFChooseIdentityPanel, SFCertificatePanel classes provide help buttons for dialogs. To display such a help button and link it to an anchor in your help book, use the methods setShowsHelp: and setHelpAnchor: in those classes.
and the documentation for these properties in NSAlert state:
-setShowsHelp:YES adds a help button to the alert panel. When the help button is pressed, the delegate is first consulted. If the delegate does not implement alertShowHelp: or returns NO, then -[NSHelpManager openHelpAnchor:inBook:] is called with a nil book and the anchor specified by -setHelpAnchor:, if any. An exception will be raised if the delegate returns NO and there is no help anchor set.
...so I know that I am using these two properly.
I also understand that I need to create a .helpindex file every time I update my Apple Help book HTML documents. I'm using "Help Indexer.app" which is in the Additional Xcode Tools on developer.apple.com. I make sure that:
- I have the option set to index all anchors.
- Any HTML page with an anchor has
<meta name="ROBOTS" content="ANCHORS">in the header so anchors are indexed. - My Apple Help book plist file correctly points to the .helpindex file created by "Help Indexer.app".
But even with all of this, I cannot get it to open the Apple Help book to the correct anchor or even the Title page of my Apple Help book.
from cover to cover multiple times and I cannot find a solution or anywhere online.
I've also tried opening it manually, but it just opens to the same error saying the specified content couldn't be found with the following code:
let bookName = Bundle.main.object(forInfoDictionaryKey: "CFBundleHelpBookName") as! String
NSHelpManager.shared.openHelpAnchor("ArrivalTimesUsingStopID", inBook: bookName)
Using nil for the inBook parameter doesn't work either:
NSHelpManager.shared.openHelpAnchor("ArrivalTimesUsingStopID", inBook: nil)
Any ideas?
I'm not sure if this is the answer at this point, but it is an answer and one that seems to do the trick. I wasn't able to get the
helpAnchorin the Alert to work, but using the help delegate, the method outlined below works.I started out my day trying to open the Help Book to a simple anchor. I'm sure this used to work using the
NSHelpManagerin the past, but it does not appear to in recent versions of the OS.Watching the console while opening my under-development App's help book resulted in the following:
Opening to my anchor using
NSHelpManagerresulted in:And, it didn't result in opening to my anchor.
I tried appending the
*<version>to my URL:Looking deeper into the Console, though, I noticed that this is definitely triggering a network request and there's an
unsupported URLcoming back.It's not clear to me if
help:anchor=...does not function any longer, but I did find a relatively easy, but annoying way around the problem.Anchors within help will definitely be opened when using a
help:URL that is formatted like afile:URL and contains an anchor; and they will open to the correct anchor location.This requires locating the specific help book and HTML file so that you can specify precisely where to open.
Basically:
Spatial_Join.htmlis our filename, so we have the bundle look for it by name and extension.NSURLComponentsinterface to mutate theNSURLby changing the scheme fromfiletohelpand adding our achor in thefragment.It's not pretty, but it does appear to be effective and safe, at least in a non-sandboxed macOS App under 10.15.
Note that I could make some assumptions here about the help book name, but for illustration purposes this seems more clear, and because of the way resources work, it's not clear that those assumptions about the names would be appropriate in all situations.
My final result was this helper method:
Call site syntax is:
I tried getting the help bundle with
[NSBundle bundleWithIdentifier:]using the help bundle ID, but that returned nil. However,[NSBundle URLForResource:withExtension]will take anilargument for theresourceNameand get the first item that matches the extension. In my case (and I believe many) there is only onehelpresource, so this allows for a method that doesn't require knowledge of the Application's help book name.