turing complete with a stack of 0xdeadbeef

Writing

I mostly write about Swift, Objective-C, iOS, open source, and other software development topics. Sometimes I write about the ethics of tech, labor, and politics. I also write satire pieces, personal essays, and notes on what I'm currently reading.

How to automate perfect screenshots for the Mac App Store

24 March 2025

Meeting the requirements for screenshots is a frustrating experience. On iOS, tooling like SimulatorStatusMagic, Nine41, and fastlane snapshot help make the process easier. However, on macOS there is much less support (and, sadly, demand) for automated tooling — so you are kind of on your own to figure it out. I spent some time recently solving this process for myself. I want to share how I have managed to automate perfect screenshots for the Mac App Store.

Continue…

How to remove unwanted Swift Package schemes in Xcode

10 March 2025

Xcode automatically creates schemes for your app and other targets included in your project, which allow you to build and run those targets. I recently ran into an issue where Xcode was including schemes from third-party Swift Package dependencies in its auto-populated list. This automatic behavior does not cause any problems, but it can be quite annoying and distracting to have unwanted schemes from packages pollute your list of schemes.

Continue…

AI Code review is always wrong

04 March 2025

I work on a team that has enabled an AI code review tool. And so far, I am unimpressed. Every single time, the code review comments the AI bot leaves on my pull requests are not just wrong, but laughably wrong. When its suggestions are not completely fucking incorrect, they make no sense at all.

Continue…

Xcode Tip: spell checking

24 February 2025

Did you know that Xcode can spell check your code and comments? Based on my experience working on large teams and large Xcode projects, this is a little-known feature. I routinely find spelling errors, not only in code comments but in symbol names. For the latter, this is particularly frustrating when a misspelled symbol is widely used because correcting that error — a rename that affects a substantial portion of the codebase — produces a large diff. Once you notice that your entire team has been passing around a “databaesQuery” for six months, it will drive you insane until fixed.

Continue…

Reading Notes: From misery to boredom to anxiety

20 February 2025

The zine, We Are All Very Anxious: Six Theses on Anxiety and Why It is Effectively Preventing Militancy, and One Possible Strategy for Overcoming It, was published by The Institute for Precarious Consciousness and CrimethInc in 2014. (Anarchist Library, Zine PDF). I decided to read it again recently because it felt relevant to the current political moment in the US. It is as prescient as ever.

Continue…

Type erasure for Equatable and Hashable types in Swift

Lessons from ReactiveCollectionsKit 19 February 2025

Type erasure is a method to abstract and encapsulate heterogenous generic types inside a single non-generic concrete type. In programming languages with generic types, this is a mechanism for runtime polymorphism which allows you circumvent the constraints of generics at compile time. In the early days of Swift, generics were more challenging to work with — in particular, protocols with associated types. As of Swift 5.7 (and SE-0309: Unlock existentials for all protocols), type erasure is now a feature of the Swift compiler. However, there are still situations where you may need to manually write your own type-erased wrappers.

Continue…

Introducing ReactiveCollectionsKit

A Swift replacement for IGListKit 18 October 2024

I recently released a new open source project called ReactiveCollectionsKit. It is a modern, fast, and flexible library for building data-driven, declarative, reactive, and diffable collections and lists for iOS. This library is the culmination of everything I learned from building and maintaining IGListKit, ReactiveLists, and JSQDataSourcesKit. The 4th time’s a charm! 😅 🍀 I truly hope this is the last UICollectionView library I ever write and maintain. I think it will be. You can find the documentation here.

Continue…

Kintsugi

16 October 2024

Kintsugi — no, not that Kintsugi — is the the Japanese art of repairing broken pottery. The process involves mending the breaks in the ceramics with urushi lacquer, essentially gluing the pieces together and filling in any gaps to smooth it out. At the end, you finish off the cracks with a gold powder, which highlights and emphasizes the flaws in the piece rather than attempting to conceal them. The result is a restored piece of pottery or teaware that can now be put back to use.

Continue…

SwiftUI app lifecycle: issues with ScenePhase and using AppDelegate adaptors

29 June 2024

SwiftUI introduced the ScenePhase API in iOS 14 and macOS 11. This was SwiftUI’s answer to handling application lifecycle events. At the same time, SwiftUI introduced UIApplicationDelegateAdaptor for iOS and NSApplicationDelegateAdaptor for macOS, which allow you to provide an AppDelegate on both platforms to receive additional application lifecycle events and other events that were missing from SwiftUI at the time. Unfortunately, many of those application event APIs are still missing and ScenePhase has a number of bugs (or at least, unexpected behavior).

Continue…

Swift concurrency hack for passing non-sendable closures

Uncheck yourself before you wreck yourself 05 June 2024
Updated: 05 June 2024

If you have attempted to adopt Swift Concurrency in your codebase, you have certainly needed to address dozens — likely, hundreds — of warnings and errors. Sometimes the issues can be resolved by addressing them directly. That is, your code was incorrect and you simply have to fix it to make it correct. In other scenarios, the resolution is not so straightforward. In particular, it is difficult to satisfy the compiler when working with APIs that you do not own that have not been updated for concurrency. Or, you may have found yourself in a situation where you know your code is correct, but the compiler is unable to verify its correctness — either because of a few remaining bugs in Swift Concurrency, or because you are using @preconcurrency APIs.

Continue…

Workaround: Xcode deletes Package.resolved file and produces 'missing package product' errors

29 May 2024
Updated: 30 May 2024

More and more Apple Platform developers are migrating away from CocoaPods in favor the Swift Package Manager, which is Apple’s first-party tool for managing and integrating dependencies. While it is still not quite a complete replacement for CocoaPods, it is getting closer. Unfortunately, SwiftPM’s integration with Xcode still has a number of shortcomings, even though it was introduced with Xcode 11 — 4 years ago. The worst bug is that Xcode frequently and randomly deletes the Package.resolved, which in turn produces dozens or hundreds of 'missing package product' errors. Here’s how I’ve worked around this bug on a team I work on.

Continue…

The curious case of Apple's third-party SDK list for privacy manifests

29 April 2024
Updated: 30 April 2024

At last year’s WWDC, Apple introduced privacy manifests. They recently sent out a reminder that the deadline for complying with these new requirements is May 1. Privacy manifests expand on the previously introduced privacy “nutrition labels” that are self-reported by developers and displayed on the App Store. Developers must start including a privacy manifest in their apps by the aforementioned deadline, but what’s more interesting is that Apple is, for the first time, imposing these new privacy rules on third-party SDKs as well. Even more interesting is the list of SDKs that Apple has published, which, upon inspection is quite bizarre.

Continue…

A simple fastlane setup for solo indie developers

22 January 2024

I recently setup fastlane for one of my indie apps, Taxatio, to automate uploading builds and metadata to the App Store — by far, one of the most tedious tasks of app development. While I had used fastlane extensively before when working on teams at companies, I had never actually set it up from scratch. In this post, I want to share how to do that, as well as a lightweight configuration that I think works well for solo indie developers — folks on a team of one!

Continue…

Swift protocol requirement quirks

17 January 2024

Perhaps “quirks” is not the correct description, but I recently encountered some unexpected behavior when modifying a protocol in Swift. While I was initially slightly confused, how Swift handles protocol requirements does make sense — conformances are more lenient than you might think!

Continue…

App Store screenshot requirements need to change

16 January 2024

Providing screenshots for the App Store has always been a tedious and time-consuming process. But as the number of differently-sized iOS devices has grown and changed over the years, it has become more difficult to manage. (This is why the developer community built tools like fastlane snapshot.) The screenshot requirements for the App Store have increasingly become a burden for developers, especially indies. With the Mac App Store, there are fewer hurdles and less strict requirements. However, if you are now targeting only the latest OS releases and latest hardware, the screenshot requirements for both App Stores are not only burdensome but they no longer makes any sense!

Continue…

A list of books I read in 2023

29 December 2023

Continuing another tradition, here are the books I read in 2023. Similar to my previous post highlighting my top posts of 2023, I also skipped publishing my reading list last year, for 2022. Again, I was simply too burnt out by the end of that year. I also did not read that much compared to previous years — thanks again to burnout. You can find previous years here under the #reading-list tag.

Continue…

Top posts of 2023

29 December 2023

To continue my (almost) tradition of sharing my top posts, here are my most popular posts of 2023. You can find previous years here under the #top-posts tag. Last year, 2022, is notably absent from this series — I was too burnt out last year (for a number of reasons) to write one of these posts. So as a bonus, I’ll include my top posts of 2022 here as well! As usual, all of my analytics data is publicly available, made possible by the excellent GoatCounter Analytics, so you can view it too.

Continue…

How to fix Mac menu bar icons hidden by the MacBook notch

16 December 2023
Updated: 29 May 2024

Last week I wrote about setting up a new MacBook Pro — my first Apple Silicon Mac, and thus my first MacBook with a notch. I lamented how poorly macOS interacts with the notch, specifically how menu bar apps and icons simply get hidden if you have too many to display. Lots of folks on Mastodon offered various solutions, and some readers emailed me with options as well. I figured it was worth making a separate post about this specific issue to list all of the workarounds and alternatives. It is clear that this is a widespread problem that users are having.

Continue…

Going Indie: bookkeeping and invoicing

07 December 2023

Welcome to the fourth (and I think final!) part of my going indie series! Previously, I discussed the exciting topics of business structure, taxes, and retirement. Today, I’m going to discuss two final topics: bookkeeping and invoicing. The first is about how to correctly track your income and expenses, and the second is about making sure you get paid! Because this is capitalism, baby — we are not here for passion, we are here to pay those bills.

Continue…