Making A Mac App

12 February 2019

When I was finishing up Daily Dictionary for iPad, App Review decided that it no longer found my subscription upgrade screen acceptable despite its design not changing. They took issue with the verbiage in the fine print, they complained that Terms and Privacy Policy link must not be blended together and instead separated into two independent links, etcetera etcetera.

This is annoying but it is not unusual. App Review loves to changes its mind and never more so than with the renewing subscription requirements. On this occasion, I had ‘nothing’ to do whilst I was waiting in the metaphorical App Store Connect line. It was a weekend.

For some reason, I channeled my frustration from the repeated delays into making a Mac app. I booted up a new Xcode project and tried to learn AppKit on the spot. I had approximately zero prior knowledge about Mac development, and it seemed like a terrible time to start given the turbulent state of macOS apps framework, but I had nothing better to do.

AppKit is funky. I have now made a Mac app, but I admit I don’t know what I’m doing. When you get stuck with AppKit, you really do get stuck. Googling doesn’t really help you as there simply is a lack of online posts and forum threads for Mac-specific topics. I basically followed UIKit idioms whenever the most obvious path was not apparent.

Some stuff came very naturally. Other stuff seemed inane, or at least I don’t have the context or berth to understand the choices that have been made.

I thought it was really cool that behaviours like alternate menu items in the menubar are built-in automatic features of the AppKit framework. (This is the thing where you can hold down a modifier key, like Option, whilst in a menu and see how some of the items dynamically update to show an alternate-but-related action that depends on the modifier key being held.) As a developer, you just add two menu items with concomitant keyboard shortcuts, set a flag, and it shows and hides the secondary one automatically. In general, AppKit has a much larger library of controls and interface elements than UIKit such that the need for coding custom view subclasses is greatly reduced. Also, macOS standard elements look prettier than the stock iOS counterparts, so that helps a lot too.

In the ‘stupid stuff’ camp, it is ridiculous that you can’t zoom in or out of a Mac storyboard in Interface Builder. I was flummoxed when it came to making an action that could be executed with a keyboard shortcut without having an activatable control on the screen. I also struggled to work out how I was supposed to organise my Mac project. How do I funnel menu items from a storyboard into outlets for my window controller? The solution I found is to make outlets on the AppDelegate that I then expose as public properties. Yuck.

Despite the bumpy road, my familiarity and ten year knowledge of iOS app development meant that I could complete the work. I have made a single window utility Mac app, and doing it was really fun. I originally made it as a personal proof of concept but it turned out so good that I polished it up into a shipping app.

What is that app? Tabs to Links. It detects open windows and tabs in Safari and lets you export those tabs as a list of links. In one step, you can make a bulleted list in Notes or just send the links in an email. There’s also an integrated suffix algorithm, which allows the app to strip redundant text from the links. This comes up a lot as many websites include their name and/or slogan in the page title. Just check the ‘Trim titles’ box and the app finds such repetition and will not include it when sharing. Click the Share Links button to see all compatible sharing services. If Tabs to Links is frontmost, you can press Command+C to instantly copy to the clipboard, ready for pasting into any Mac app.

You can get it now from the Mac App Store. Watch this 15-second demo video I made using my incredible (read: terrible) iMovie and QuickTime skills. It works with Safari only; I could make it work for Chrome too if there is demand.

Here’s an amusing aside. Years ago, I made this feature as a tabs-to-links Safari extension. It would take the open tabs and spit out a HTML list. Me and Zac have used it for ages to create the show notes for the Happy Hour podcast.

Apple’s migration to Safari app extensions, from Safari JS extensions, removed the capability to detect all opens tab in a window; you could only get the name and URL of the active window. Hence, my hacked-together JavaScript extension did not have a future. This was the underlying motivation to remake the project when I decided to dive into AppKit; I knew it would be relatively simple but also useful.

Sods law is such, that upon completing the native Mac version, Safari Technology Preview added an API for app extensions to retrieve data for all windows and tabs. This means Tabs to Links could live as an app extension after all. In any case, the Mac app is way nicer to use. AppKit enables more features, a prettier UI, and access to system sharing services. Down the road, I could integrate a Safari extension into Tabs to Links as an alternative option.