17

By default, Mac Catalyst creates a menu titled "Help" that is supposed to include help for the application. However, I found no documentation on how to implement Help. For standard Mac apps, you can use a Help book. However, there is no mention on how to use a help book with Mac Catalyst. I attempted to add the HelpBookDirectoryName to info.plist but this did not work. Is there a way of making help books work with Mac Catalyst?

Ken Roe
  • 251
  • 1
  • 6

6 Answers6

13

We use a web-based help system for our iOS app and adding this to the appropriate UIViewControllers seems to work to connect the Help menu command for our Catalyst version:

    // Show some help.
@IBAction func showHelp(_ sender: Any) {
    UIApplication.shared.open(URL(string: "http://www.ourapp.com/faq")!)
}

// Return whether action can be performed.
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {

    if action == #selector(self.showHelp(_:)) {
        return true
    } else {
        return super.canPerformAction(action, withSender: sender)
    }
}
LenK
  • 2,944
  • 2
  • 20
  • 26
8

OK... I managed to get this to work by using a third party app (Help Crafter) to create the MyAppName.help file/folder, but you could do it manually.

Once you have created the MyAppName.help file, you need to copy it to the Resources folder in your project. I did this first by copying the file to the Resources folder in Finder, and then dragging that file into the Resources folder in Xcode.

The most important step: Select 'Create Folder References' when dragging it into your project.

I had previously selected 'Create Groups' and it never worked.

This link has some useful information too, particularly if you're going to create the MyAppName.help file manually

http://swiftrien.blogspot.com/2015/06/adding-apple-help-to-os-x-application.html

In short, there will be a .plist file contained inside the MyAppName.help file/folder, but you'll need to add two keys to your projects .plist file too:

  • Help Book directory name -> the name of your .help file (which is technically a directory with a .help extension)
  • Help Book identifier -> for me it was maccatalyst.com.nitramluap.MyAppName.help but it has to be the same identifier in the MyAppName.help .plist under the key Bundle Identifier
Paul Martin
  • 699
  • 4
  • 13
2

After some testing. I found the following methods works best for me. For a MacCatalyst app.

Steps:

Adding the following code to AppDelegate. Thus remove the default help.

override func buildMenu(with builder: UIMenuBuilder) {
    super.buildMenu(with: builder)
    builder.remove(menu: .help)
}

Add the following selector to AppDelegate. This will provide a link to your help website.

@IBAction func openHelp() {
    UIApplication.shared.open(URL(string: "https://www.legolas.me/blankbook-english")!)
}

Lastly, add the following code to the buildMenu function. After builder.remove.

let helpCommand = UIKeyCommand(input: "W", modifierFlags: [.command], action: #selector(openHelp))
helpCommand.title = "Blankbook's Guide"
let helpMenu = UIMenu(title: "Blankbook's Guide", image: nil, identifier: UIMenu.Identifier("guide"), options: .displayInline, children: [helpCommand])
builder.insertChild(helpMenu, atStartOfMenu: .application)

This is the end result: enter image description here

Legolas Wang
  • 1,951
  • 1
  • 13
  • 26
  • Was this allowed in the App Store? The OP said that their app was rejected because they didn't have a Help menu. Your example doesn't have a Help menu either. – leanne Jul 28 '20 at 19:38
  • 1
    @leanne I’m using it in my app. And it’s live in the App Store. So I guess yes? – Legolas Wang Jul 30 '20 at 00:41
  • Why would you use Cmd-W to open help? Cmd-W is the standard command to close the current window. That's really confusing. – HangarRash Jun 06 '23 at 00:35
0

The easiest way is just to override the buildMenu(with:) function. I use this in my App Delegate:

override func buildMenu(with builder: UIMenuBuilder) {
    if let helpMenu = builder.menu(for: .help) {
        let helpKeyCommand = UIKeyCommand(input: "?", modifierFlags: [.command], action: #selector(helpAction))
        helpKeyCommand.title = NSLocalizedString("YOUR_APP_NAME Help", comment: "")
        let newHelpMenu = helpMenu.replacingChildren([helpKeyCommand])
        builder.replace(menu: .help, with: newHelpMenu)
    }
    
    super.buildMenu(with: builder)
}

@objc private func helpAction() {
    // Perform your action here
    print("help!")
}
Oscar
  • 404
  • 7
  • 19
0

I appreciate that it's a couple of years since this issue was last discussed but I was hoping that one of the answers to it would allow me to add a Help menu link to an online guide for an iOS app that I have recently ported to macOS via Mac Catalyst. My app uses the SwiftUI lifecycle so I had to add an AppDelegate manually, which I did following guidance at hackingwithswift.com. Oscar's reply helped me on my way and I was able to insert a link in the Help menu; however, the link was always disabled. Eventually I found a solution, which was to discard Oscar's helpAction() @objc function and to replace:

let helpKeyCommand = UIKeyCommand(input: "?", modifierFlags: [.command], action: #selector(helpAction))
helpKeyCommand.title = NSLocalizedString("YOUR_APP_NAME Help", comment: "")
let newHelpMenu = helpMenu.replacingChildren([helpKeyCommand])
builder.replace(menu: .help, with: newHelpMenu)

with:

let openHelpAction = UIAction(title: "YOUR_APP_NAME Help") { (action) in 
//Your code here
}
let newHelpMenu = helpMenu.replacingChildren([openHelpAction])
builder.replace(menu: .help, with: newHelpMenu)

The action code in my own openHelpAction is simply:

UIApplication.shared.open(URL(string: "https://www.crizzle.co.uk/inetworthHelp/index.html")!)

I now have an operational Help menu capability in the Mac Catalyst version of my iOS app and I will be uploading the new version to the Mac App Store very soon. By the way, I have not had any issues with the lack of a help capability resulting in app rejection by the App Review process. I used to ship .help files with my apps but something changed to the .help UTType between Big Sur and Monterey, making the display of help files in HelpViewer very hit and miss, so I started shipping my apps with links to an online guide to be sure that help is always available (as long as the user is online); a side benefit of doing this was a significant reduction in the size of my app packages.

Another 'by the way' that might help users, who are based in the UK (where Help Crafter is not available) and want to generate Apple-like online help guides, is a suggestion to try out the help file generation capability at this link: Middlemac. Middlemac is not as easy to use as Help Crafter and requires extensive use of the CLI in Terminal; however, the results are, I believe, very good.

0

If you'd like to remove the App Help menu item, perhaps to replace it with custom commands to open your website, contact support, view frequently asked questions, etc, you can replace the children of the Help menu with your own commands like so:

override func buildMenu(with builder: UIMenuBuilder) {
    super.buildMenu(with: builder)
        
    guard builder.system == .main else { return }

    builder.replaceChildren(ofMenu: .help) { menuElements in
        // We don't support App Help menu item as of now, so create our own custom menus
        return [
            UIMenu(options: .displayInline, children: [
                UICommand(title: "Frequently Asked Questions", action: #selector(faqsAction)),
                UICommand(title: "Contact Support", action: #selector(contactSupportAction))
            ]),
            UIMenu(options: .displayInline, children: [
                UICommand(title: "Privacy Policy", action: #selector(privacyPolicyAction)),
            ])
        ]
    }
}
Jordan H
  • 52,571
  • 37
  • 201
  • 351