Newsletter Revival

Not everybody knows how to consume RSS, so I wanted to try to make updates to the blog available via email.

That’s why I have now revived the newsletter signup page.

This is the plan:

  1. You get virtually no messages by default,
  2. you can subscribe to automatic updates based on the blog’s feeds.

I’ll experiment with this setup for a while, but I think the current options cover almost anything I currently do, or plan to do, so that both developers and customers of my apps get something interesting in their mailboxes.

With regard to GDPR compliance I went a bit over the top and included a ”GDPR Consent Checkbox” for email delivery, just in case, even though everybody seems to agree that the mere act of subscribing is enough already. So you won’t get anything unless you check that, and update your

If you were subscribed to my newsletter before, please revisit the new settings so you can adjust which kind of updates you get. I have sent a message with information to everyone on the old lists, so you should’ve received instructions already.

TextMate v2.0 Was Released

The TextMate auto-updater surprised me yesterday by installing v2.0. No RC suffix anymore, just the plain number. That doesn’t mean this update comes with any crucial feature. It’s just a message of intent: this editor is worthy to be a successor to TextMate 1.

I think TextMate 2 was good enough for years already. In fact, only in 2019 did I begin to see weird behavior in my basic workflow with it. The async text highlighting seems to cache less than before, so that switching tabs throws off what’s visible in the editor view, and new windows start too small to fit the line wrapping all of a sudden. But does that bother me very much? Nope. I use TextMate every day. I maintain this and any other website with this editor. I write every Ruby script with TextMate. (For a Raspberry Pi Python project, I used Emacs to remotely edit on the device via SSH, though.) I write and edit my book manuscripts with TextMate. Whenevery I need to have multiple carets to edit similar lines of text, I go to TextMate. (Though I never tried the macro recorder.) It’s always open, and it’s the first app I install on new Macs. It became a part of me, and I don’t like the thought of someday having to miss it.

Get TextMate 2 for free. It’s open source.

State of the macOS Developer Platform Choices

2019 is a weird year for developer platforms.

Microsoft App Center will incorporate HockeyApp. HockeyApp is discontinued in November 2019. The App Center will be supporting Sparkle feeds in the future, too. So Microsoft will offer a service that may be useful to deploy macOS apps, soon?

Google Firebase will incorporate Crashlytics/ will be discontinued in March 2020, too. Using Firebase for macOS apps was possible, but iOS was the real target platform. Fabric seemed to be popular, so I was surprised by the news of this.

DevMate is sunsetting in December 2019. So you’re left with Paddle, which are going to focus more on software-as-a-service than indie developer apps, according to a source. As long as they stay afloat and keep the existing native app libraries functional, that’s not bad news per se, though.

I don’t know of any other rady-made solution for indies to sell apps. Do you?

Is there just not enough money to be made to warrant the cost of support and hosting?

Update 2019-09-17: Even the Open Source dinosaur PLCrashReporter (previously at is now stewarded by Microsoft, I guess as part of the HockeyApp integration.

Please Also Change Your Feed URL’s Inside Your Apps

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:

  1. Redirect the remote feed URL to deploy updates to existing customers working with old versions, and
  2. 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.

See also:

Redirect Your DevMate Sparkle Update Feeds Now

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.

You should, of course, also send them an email with transition instructions. Please don’t just rely on the update server approach to work, because eventually might be gone for good, and then the redirects won’t work anymore.

The update URLs for DevMate follow a very simple format:

To look up the BUNDLE_ID, Head to your Settings > Basic App Details in the DevMate dashboard. There, you can set the App Icon and see the App Name and Bundle ID. Since the text fields are disabled, you may need to inspect the HTML source in your browser to conveniently copy the contents.

Download the feeds for reference and upload them to your servers. Then ask the DevMate support to redirect to your place.

Currently, it seems this process takes quite a while. A couple of weeks, in fact. I don’t know if that’s because of their high support ticket volume, or because they are still coding the infrastructure for update redirects.

Either way, I highly recommend you do this now so your redirect is functional rather sooner than later.

Update 2019-09-14: Oh, and also deploy an update with the new feed URL so you don’t rely on the redirect for longer than absolutely necessary!

I Am at Macoun 2019

I’ll be at this year’s Macoun developer conference in Frankfurt (Main) again. This time, I’m not giving a tech talk, but hosting a workshop with Oliver Böhm.

The Macoun is a German conference, and it isn’t expensive. I think that’s a great combo. You should go if you can. The community, or family, built around the conference over the past dozen years is very, very welcoming. You cannot not learn something when you attend.

Be there or be square!

Wireframe for Server-Side License Activation

Server-side app license code validation, as I imagine it, in a nutshell:

  1. Server generates license code during the purchase (via e-commerce store’s FastSpring order fulfillment).
  2. App sends code to the server, requesting authentication. The app cannot unlock itself with the code, as opposed to offline licensing.
  3. Server responds with error, or an authentication token. The token can contain an expiration date if really, really want to enforce perpetual re-activation.
  4. App stores current authentication token, license code for later requests, and adheres to the token renewal policy.

If the token expires and there’s no server connection, you have to figure out how punishing you want to be. I suggest you do not punish by default and assume people have good intentions.

Possible escalations:

  • The app can immediately lock itself unless re-activated. This renders the app useless if your server goes down, which it will, eventually. Same problem as with Games as a Service.
  • The app displays a warning but goes into a grace period where it is still usable. Could be weeks or months. Some polar expeditions take a while, so be lenient if you give a grace period at all.
  • The app displays a warning but doesn’t ever lock functionality. Could be a window decoration label, similar to how trial periods are sometimes displayed in the top-right corner.
  • The app doesn’t do anything in response, silently waiting for the connection to the server to come back up eventually.

Remote or server-side deactivation of licenses can be useful to prevent continued use after refunds.

Become an Acquired Taste

Seth Godin points out that people usually say “an acquired taste” as if that is something bad. I never thought about this phrase much, but he does have a point here. Indie developers and creators in general should consider to be a pleasure for the introduces few: that thought is in line with getting your first 1000 true fans, and everything the crew at Basecamp (formerly 37 Signals) around Jason Fried preach for years. Retain your individuality. Make something that is indispensible for people instead of making a throwaway mass product.

Examples of consumables that people are fine with becoming acquainted to through experience and testing:

  • Good coffee
  • Dark chocolate, as in 85% and more
  • Green teas
  • Wine

UINavigationController Inside a Popover

Noah Gilmore wrote about his approach to use UINavigationController inside a popover without subclassing the navigation controller. Even though I don’t work on iOS apps, like, at all these days, this sounds too useful to go by unnoticed.

Hopefully this was a helpful look into the world of preferredContentSize, view controller wrapping, and UIKit popovers. Here’s a tl;dr:

  • To define the size of your popover with autolayout, set preferredContentSize to the result of systemLayoutSizeFitting
  • To animate popover size updates at the same time as navigation controller animations, wrap your UINavigationController in a PopoverPushController (see code below)
  • When you change your controller’s preferredContentSize, be sure to change the preferredContentSize of your controller’s popoverPresentationController’s presentedViewController as well

See NGPopoverForceResizeTest, the resulting sample app on GitHub.

→ Blog Archive