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.

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…

How to fix malfunctioning AirPods

14 November 2023

A few weeks ago my AirPods Pro 2 (with Lightning, not USB-C) suddenly started acting buggy and weird. The case no longer made the chime sound when plugging them in to charge. I stopped getting “Left Behind” notifications from the Find My app. After updating to iOS 17, I could not get them to install the latest firmware, which enables the new features for Adaptive Audio, Conversation Awareness, and Personalized Volume. I had been trying for weeks to follow the magic steps that will trigger a firmware update with no luck. Even worse, after a full charge of both the AirPods and the case, the batteries for all of them would drain to zero percent within 2-3 days.

Continue…

GitHub Tip: using the involves filter

30 October 2023

When you work on a large team and are participating in many pull requests on GitHub, it can be difficult to keep track of everything you are working on. In addition to opening your own pull requests, you can be assigned to them, you can be requested as a reviewer, you can comment in discussion threads, and you can be mentioned by others. Each of these occurrences requires your attention — perhaps immediately, but always eventually.

Continue…

Swift URL absoluteString versus path

17 August 2023

Foundation’s URL (née NSURL) is a nearly ubiquitous API on Apple platforms. One of its shortcomings is that it is heavily overloaded – an instance of URL could represent a web URL or a file URL. While there are many similarities between accessing resources on a local disk or on a web server, I think there should be explicit types for each, say WebURL and FileURL.

Continue…

How to customize NavigationLink accessory views in SwiftUI

18 July 2023

In UIKit, UITableViewCell has a customizable accessory view. You can use one of the few accessory options that is provided by iOS by setting the accessoryType property, or you can provide a custom view using accessoryView, which can be any UIView. The equivalent of constructing a UITableViewCell with a chevron accessory in SwiftUI is using a NavigationLink. Unfortunately, however, SwiftUI does not provide an API to customize the accessory view for a NavigationLink — you are stuck with the default chevron.

Continue…

Stop prefixing your UserDefaults keys

17 July 2023
Updated: 17 July 2023

UserDefaults is probably one of the most popular APIs on Apple Platforms. It is a highly-optimized key-value persisted store that is backed by a property list, and it is most commonly used for saving small pieces of data like user preferences. Despite its ease-of-use, there is one common anti-pattern I see developers use often.

Continue…

Creating dynamic colors in SwiftUI

11 July 2023

Beginning with the introduction of dark mode in iOS 13, colors in iOS are now (optionally) dynamic. You can provide light and dark variants for all colors in your app. However, I was surprised to find that SwiftUI — which also made its first appearance on the platform in iOS 13 — still does not provide any API for creating dynamic colors.

Continue…

Introducing Taxatio

24 April 2023

I’m excited to share that I recently released a new app, a tax calculator for freelancers called Taxatio. It is specifically for self-employed sole proprietors based in the United States — freelancers, consultants, independent contractors, and indie developers (like me!). One of the more confusing and difficult aspects of going independent is taxes. And that’s why I made this. It is a multiplatform SwiftUI app for iOS and macOS available as a universal purchase on the App Store.

Continue…

Exploring a new iOS codebase

04 April 2023

Whether you are starting a new job or joining a new project, getting oriented in a new iOS codebase can be difficult and overwhelming. It is particularly hard if the codebase is very large, and especially challenging if you are early in your career and do not yet have much experience to draw from.

Continue…

Improving multiplatform SwiftUI code

23 March 2023

For multiplatform projects where I’m using SwiftUI, it certainly makes developing for multiple platforms at once significantly faster. However, each of Apple’s platforms are different enough that eventually your codebase will be littered with #if os() checks.

Continue…

Xcode Tip: filter to show modified files only

22 March 2023

Large Xcode projects can be difficult to navigate, especially when you are making a large change across a large number of files. Depending on how your project is configured, modified files will be spread across multiple nested directories and multiple targets.

Continue…

Xcode Tip: filtering debugger output

02 March 2023

When debugging a large project in Xcode that a large team works on, the console can get quite busy. Logs are everywhere! It can be difficult to sift through the noise, particularly when you have a number of breakpoints configured to log messages, execute debugger commands, and continue after evaluating rather than pause.

Continue…