Nathan Manceaux-Panot shared his contribution to Sparkle the other day, available in version 2.5 of the de-facto standard updater library for Mac: attaching CSS to parts of the release notes that are actually new to the user. Say you ship updates in x.x.1 increments to beta testers, but x.1.x updates on your public release channel.
An old code base was still using Sparkler v1.27.0. To test the transition to the latest 2.x branch, the one that allows Sandboxing and uses XPC services under the hood, I migrated that project. Carthage builds of Sparkle’s v2.x branch don’t work well, though. You would need to do a lot of manual re-signing, otherwise the code signing stage of your build will fails. It does with a simple test project that embeds and signs the framework.
TL;DR: The Sparkle 2.x release branch is working fine for production when you switch from the ui-separation-and-xpc branch and enable DSA signing of updates. While updating TableFlip for macOS Big Sur, I figured I might just as well update my dependency on Sparkle to whatever they came up with in the past 18 months or so.
In my post about redirecting the DevMate update feed, I missed the opportunity to mention that you should probably also update your app very soon to not rely on DevMate’s framework.
Mr Boy van Amstel at Danger Cove picked up the topic and explains how you can change your feed URL inside the app using the Sparkle SUUpdaterDelegate methods. DevMate’s closed-source framework wraps this in its DM_SUUpdaterDelegate_DevMateInteraction protocol.
Your battle plan thus should be:
Redirect the remote feed URL to deploy updates to existing customers working with old versions, and
Change the feed URL used inside the app as soon as possible and deploy an update to not rely on the redirect for too long.
I use the SUUpdaterDelegate to switch feed URL’s in The Archive and WordCounter, too, in case you wonder if this is a good idea in the first place.
Fellow developer Daniel Kennett mentioned that he requested a HTTP redirect for the DevMate feed to his own server. I probably wouldn’t have thought of this, and think it’s a great idea. This way, you can reach DevMate customers long after their servers have stopped responding.
In the previous post, I talked about how to download the “modern” Sparkle updater branch called ui-separation-and-xpc that allows you to update sandboxed apps and migrate your code to use the new types. This time, we’re going to use the actual XPC services that do the grunt work.
The Sparkle XPC fork is even better than I would’ve imagined! As I mentioned in the previous post about Sparkle’s XPC branch, you can switch to the new framework version and the new types without having to change much else. The new API is very similar to the old one. If you switch to the work-in-progress ui-separation-and-xpc branch, then you can continue to use CocoaPods or Carthage if all you want is the new API.
This is the first post in a series: The standard solution to provide app updates outside the Mac App Store is to use the amazing Sparkle framework. The releases of Sparkle don’t support sandboxed applications well, though, so the core maintainer Kornel Lesiński (@kornelski) is working on a more secure fork of Sparkle next to the existing one. He’s maintaining the regular Sparkle, and the fork. The fork features various XPC services to deal with Gatekeeper security configurations and Sandbox entitlements in a proper way. (I have to phrase it in such a vague way because I have no clue about the details, yet. Explanations are very welcome in the comments!)
The default Interface Builder approach of using a “Shared User Defaults Controller” object breaks down if your app preferences are not stored in the standard place. Both my apps The Archive and the Word Counter for Mac are comprised of multiple executable applications. For The Archive, it’s the main app and the Quick Entry popup window. They share some settings, like which theme and font size is used. To share these settings, I rely on NSUserDefault (or just UserDefaults in Swift now). I cannot use the UserDefaults.standard, though, because that is tied to the currently running app’s bundle ID. In the case of the main app, it’s the ID of the main app; but for the Quick Entry helper – or any helper app –, it’s the helper’s bundle ID. This way, the defaults dictionaries are not shared.
I got burned this week. Pretty bad. I shipped a small bugfix release for my Mac app Word Counter a couple of days ago to prepare for the “big one” coming this week. Naturally, I built that version on my El Capitan dev machine. I pushed the update to my server. Updates using Sparkle worked. – But now users of that version cannot ever update to the next version. Because I haven’t thought about ATS.