turing complete with a stack of 0xdeadbeef

Writing by tag

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

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…

Setting up a new M3 MacBook Pro

04 December 2023

I typically try to keep devices for as long as I can — historically, that’s been around 5-6 years for laptops. During the Intel era of MacBooks, the year-over-year spec bumps were usually not impactful enough to justify more frequent upgrades. However, the transition to Apple Silicon has changed that. I recently upgraded to my first M-series MacBook Pro.

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…

Going indie: business structure, taxes, and retirement

16 August 2023
Updated: 17 August 2023

Welcome to the third part of my going indie series! In the previous post, I discussed building a foundation, getting started, and finding clients. In this post, I am going to discuss many of the decidedly un-fun administrative aspects of being freelance and contracting like saving for retirement and — everyone’s favorite — taxes. Most folks consider these topics to be boring and tedious, but understanding them is critical to your success. The best approach is one of curiosity. As a software developer, you might find the task of optimizing (and minimizing!) your tax burden to be an interesting problem to solve — I definitely do!

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…

Going Independent

My experience and reflections 3 years later 10 April 2023

A number of folks have reached out to me recently (and over the years) asking me about my experience going indie. I originally wanted to write this reflection after my first year, but I could not find the time nor motivation. The early days of the pandemic really drained me. However, I hope these past three years of experience will only make this post more valuable to those seeking to do the same thing I did. I am writing this for anyone who is interested in trying to go independent — either with your own app development business, solo contracting and freelancing, or both.

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…

Love for hardcore, and a taste of karma

02 April 2023

I grew up in the 90s and early 2000s. I was a skater kid and when I wasn’t skateboarding I was playing Tony Hawk’s Pro Skater on my Playstation. That scene introduced me to punk music, which eventually led me to hardcore music. By my early teens I was going to shows nearly every week with my friends.

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…

Make your terminal tell you when it's done

22 February 2023

When working on large iOS apps, all the tasks you need to perform before you even get started writing code can begin to consume a lot of time. I’m talking about all the preparation that happens in your terminal — pulling the latest changes, bootstrapping the project, etc. During this wait, I usually take a moment to follow-up on emails or Slack messages. But the problem with that is I inevitably end up getting pulled deeper into those tasks and forget to return to the terminal, open Xcode, and start working.

Continue…

Xcode tip: sharing breakpoints across projects

21 February 2023

In my previous post, I explained how to use symbolic breakpoints to discover when view controllers load their views into memory. Often breakpoints are specific to a project. You’ll create one for a specific class that only exists for that particular app. However, what I discussed in that post would be useful in any project. Unlike regular breakpoints, symbolic breakpoints (at least when set on system frameworks) are more or less universal.

Continue…

How to find and fix premature view controller loading on iOS

20 February 2023

While working on a very large iOS client project, I was investigating the causes for our slow app launch time. We had a hypothesis that part of the problem was that too many view controllers were getting loaded in memory, in particular, ones that were not even being presented to the user during app startup. What could cause view controllers to load too early? How might you discover this happening? And how do you fix it? Let’s find out.

Continue…

Goodbye, Twitter

06 February 2023
Updated: 03 April 2023

When I wrote about joining Mastodon, I said I would stay on Twitter for the moment and see what happens. Well, unsurprisingly, the service has continued to erode. It really is a shame, because I’ve found the software developer community there very helpful over the years. I met a lot of friends on Twitter, and later met them for the very first time in person at WWDC.

Continue…

Upgrading to macOS Ventura

18 January 2023

I finally upgraded to macOS Ventura recently — about a month ago. As usual, I waited until the first point release, 13.1 (22C65). Although I have experienced few severe issues with upgrading over the past few years, a couple of bad experiences and others’ reports of bugs leave me skeptical and apprehensive each year. I miss the old days of OS X when I would upgrade on day one without any concerns at all.

Continue…

Publishing an RSS feed to Mastodon

15 December 2022

If you follow me on Twitter, you’ve likely noticed that my blog posts are automatically tweeted for me. There are multiple services you can use to do this, like Zapier and IFTTT. I use both services for various automations. Each has built-in actions for listening to an RSS feed and then tweeting new items as they appear. Sadly, neither service has a built-in action for Mastodon. However, we can achieve the same results with a generic webhook action on both platforms.

Continue…

Hello, Mastodon

14 December 2022

I finally decided to create an account on Mastodon. You can follow me at @jsq@mastodon.social. I put this off for so long because I was skeptical and I did not want to manage another social account, but it has turned out to be pretty fucking awesome.

Continue…

Sharing cross-platform code in SwiftUI apps

19 August 2022

The main appeal of building apps in SwiftUI is being able to share UI code across platforms, in particular iOS and macOS. It is not perfect and you often have to do some #if os() checks, but when it works it is truly great. Before SwiftUI was around, you could already share a lot of (non-UI) code between iOS and macOS. Many of the system frameworks are available on both platforms, for example Foundation and Core Data. Occasionally there are API differences, but they rarely impose a significant burden.

Continue…

Automatically assign milestones with GitHub Actions

04 August 2022

One of the most important parts of software development is tracking changes. Documenting what is going into a release is necessary not only to simply know what changed and inform your users by writing good release notes, but also to track down issues when something goes wrong. If there’s a new bug or a new crash in your latest release, you need to be able to quickly find the change that introduced the problem.

Continue…

Disconnected

25 July 2022

I have been mostly offline for about two months. Or, at least I have not been writing here like usual, nor posting on Twitter. I have been very disconnected, particularly from work but also the internet in general, starting right before WWDC this year. I still have not watched a single WWDC video, not even the keynote. I have hundreds of unread posts in my RSS reader. And, I am a month behind on reading iOS Dev Weekly.

Continue…

May 16 dreams

16 May 2022

I wrote an essay in 2018 reflecting on the 15-year anniversary of my sister’s death. I still think it’s one of the most beautiful pieces I’ve written. Today is her birthday. Amy would have turned 35.

Continue…

Using DocC on GitHub Pages

Pros and Cons 22 April 2022
Updated: 25 April 2022

When I first wrote about DocC, I lamented the fact that it was incompatible with static hosting on GitHub Pages. Much has changed since my last post, so let’s take a fresh look. While there have been many welcome improvements to the tool, there are a few remaining issues that prevent me from adopting it for my open source projects.

Continue…

Quick 5.0 released

17 April 2022

If you develop for Apple platforms and use a third-party testing framework, you are very likely using Quick and Nimble. Otherwise, you have probably at least heard of them. I don’t use any third-party testing frameworks in my personal projects, but I have worked on teams that do. And I currently work on a team that uses Quick and Nimble, which is why it was important for me to get a recent critical bug fixed in Quick.

Continue…

Using fastlane to increment version numbers in xcconfig files

28 March 2022

If you are using fastlane to automate your release process, you might be using the increment_version_number and increment_build_number actions to bump your version and build numbers, respectively. However, if your Xcode project is configured to use xcconfig files, then you are out of luck. Shockingly, fastlane does not seem to support projects that use xcconfig files and there is a surprising dearth of information online about how to make fastlane work with Xcode build configuration files.

Continue…

Automate merging release branches into your main branch with GitHub Actions

26 March 2022

A typical release process for Git workflows involves creating a release branch, performing various tests on that branch, and applying any necessary fixes or changes to that branch. Once stable and ready to release, you create a build from the release branch, create a git tag, and finally merge the release branch changes back into your main branch.

Continue…

My website disappeared from Bing and DuckDuckGo

25 March 2022
Updated: 28 July 2022

I discovered earlier this week that my website is no longer being indexed by Bing and DuckDuckGo. In fact, it appears that it has been deliberately removed from their search indexes. On Bing, rather than display a “no results” message, it displays a “Some results have been removed” message, which is very concerning. Notably, however, Google search is working fine.

Continue…

Quickly displaying the Swift version that ships with Xcode

04 March 2022
Updated: 09 March 2022

I previously wrote about writing a custom shell command to quickly switch between Xcodes. But recently, I needed to determine the version of Swift that is bundled with Xcode — specifically the version of Swift that is shipping with the current Xcode 13.3 beta. I was pretty sure that it is Swift 5.6, but I wanted to know for certain.

Continue…

The MacBook sigh of death

15 February 2022
Updated: 16 February 2022

I have been experiencing bizarre kernel panics with my Mac lately. I have a 2020 Intel MacBook Pro, the last Intel model before the M1 debuted. It has generally been working fine. Despite poor software quality and numerous bugs lurking around in macOS, I rarely see kernel panics anymore. In fact, I can’t remember the last time I had a kernel panic before this issue. There have been no major changes on my machine and I’m on the latest version of Monterey.

Continue…

When should you use Decimal instead of Double?

01 February 2022

In Swift there are 13 numeric types. Like most other programming languages, Swift provides signed integers of various sizes, corresponding unsigned integers, and a few floating-point types. But if you’ve been developing apps for Apple platforms for any amount of time, you’ll recognize another numeric type — Decimal (aka NSDecimalNumber). When we build the model layer of an app, it’s important to choose the right type for the task we want to accomplish. For example, if we are counting ticket sales for an event, then Int (or possibly UInt) would be the most appropriate type. But if we are calculating sales tax, then we’ll need to use a floating-point type. You likely know that Double is more precise than Float, but what about Decimal? When should you reach for Decimal instead?

Continue…

Screen Time is drunk

16 January 2022
Updated: 14 February 2023

Speaking of drunk software and not being in service to our possessions, Screen Time on iOS and macOS has been shockingly buggy for me lately. It reports that I spent over 22 hours on my devices in a single day last week, and nearly 10 hours on another day this week. In both instances, a significant portion of the usage is supposedly occurring after midnight.

Continue…

NFTs and web3

16 January 2022

I mostly avoid interacting with and discussing the world of NFTs and cryptocurrencies — it’s not for me. However, a couple of blog posts caught my attention recently and I highly recommend reading them.

Continue…

Users, Privacy, and Consent

14 January 2022

In today’s issue of iOS Dev Weekly, Dave wrote “What it does prove, though, is that people don’t care much about privacy.” I agree with Dave’s sentiment here, but I don’t think this is entirely true. There is more to the story. I think people do care very much about privacy. What software over the past decade has actually proven is that people do not understand privacy — or perhaps more broadly, they do not understand software nor the various technologies they use daily.

Continue…

iMessage spam and reporting abuse

How many taps does it take to block a bad actor? 13 January 2022
Updated: 08 November 2022

iMessage is in the news again recently with a revival of years-old stories about “green bubbles” versus “blue bubbles” — and the social dynamics among teens who prefer blue bubbles while ostracizing their peers with green bubbles. There’s a lot to like and dislike about iMessage, but one thing that amazes me is that there is still no way to easily report abuse and the process for blocking spam is needlessly difficult.

Continue…

A list of books I read in 2021

30 December 2021

Here are the books I read this year, in 2021, the worst year of the century so far. You can find previous years here under the #reading-list tag. Similar to last year, I’m a bit disappointed in myself for continuing my trend of reading even less than the previous year. But I’m trying to not be so hard on myself. After two years of a fucking pandemic, I’ll consider literally anything an accomplishment — so managing to find the focus to finish each of these books is something for which to be grateful.

Continue…

My first Apple Watch: thoughts and reflections

29 December 2021

I decided to finally get my first Apple Watch with the Series 7 this year. I am typically never one to get a first-generation product — my first iPod back in the day was the iPod Photo and my first iPhone was the 3G (or maybe the 3GS?) — but I rarely wait this long if I’m interested in something. The original Apple Watch had little appeal to me at the time, and the mere existence of the $10,000 gold Edition model made the entire thing feel all the more ridiculous. But over the years as the watch hardware and watchOS improved, and as I got more into fitness, I became more interested. I’ve always felt like there’s a lot of hype around the Apple Watch — people really seem to love it. After wearing and using one for about two months, now I understand. It’s pretty damn good.

Continue…

My worst tech interview experience

01 December 2021

Everyone in tech seems to have a “terrible tech interview” story. The topic quietly orbits in the ether of our industry and periodically bursts through the atmosphere in the form of a tweet or blog post that goes viral. Despite universal loathing of our industry’s impetuous and heedless interview processes, few seem willing to improve the current standard. A recent tweet in my timeline reminded me of a story that I’ve never told.

Continue…

Reading Notes: The Abolition of Work

24 November 2021

Bob Black published his essay The Abolition of Work in 1985, though it is as prescient as ever. You can find it freely available at The Anarchist Library. As you might anticipate, it is a critique and criticism of work. The first sentence of the essay is “No one should ever work.” — a sentiment I fully endorse and which I suspect the careerist workaholics in Silicon Valley will shun as sacrilege.

Continue…

Xcode LLDB RPC server crash

22 November 2021

A few weeks ago, I wrote about this bizarre Xcode 13 crash when running tests. I just discovered the root cause for one of the issues I mentioned in that post — I think. At the very least, I have a “fix”. The issue happens when running unit tests. Sometimes the full test suite will complete, sometimes not, and then LLDB will crash. This occurs with all of my projects. It doesn’t seem to matter what I do, the crash always happens. It has been driving me crazy.

Continue…

Reading Notes: The Wage System

21 November 2021

Peter Kropotkin wrote and first published The Wage System in La Revolte in 1888. It was translated for Freedom newspaper in 1889. Surprisingly, the essay is not available at The Anarchist Library. However, you can find it in Why Work? Arguments for the Leisure Society, a collection of essays (re)published by PM Press. The essays focus on dissecting “work”, its form under capitalism, and the possibilities for an alternative society.

Continue…

SwiftUI tips for organizing multiplatform projects

19 November 2021

If you are working on a multiplatform SwiftUI project, you will start accumulating #if os() checks and #if canImport() checks. Overtime, these start to accumulate and — in addition to being unsightly — they make your code much more difficult to read. When possible, I have started to encapsulate these preprocessor directives to improve code organization and readability.

Continue…

Xcode 13 device orientation options bug

13 November 2021

This post started out as a “how to” for SwiftUI, but as I started testing and verifying I realized it is just an Xcode 13 bug. Historically, if you wanted to restrict your iOS app to specific device orientations, you would check or uncheck the various “Device Orientation” options in your project settings. You can find these by selecting your Xcode Project > App Target > “General” tab.

Continue…

First impressions of SwiftUI

12 November 2021

I’ve spent this past week diving into SwiftUI, seriously, for the first time. As you know, I’ve been keeping my eye on it since it was released, but I’ve avoided it due to a combination of hesitancy, apprehension, and just being too busy with other projects and work. However, while taking some time off from contracting work, I decided to dive in.

Continue…

Deprecating PresenterKit

06 November 2021

I’ve decided to deprecate one of my open source libraries, PresenterKit. The library has been in a sort of “maintenance mode” for awhile now. It never really became what I hoped and anticipated. I think it implemented some neat ideas and helped removed some boilerplate from UIKit, but I don’t think what it provided necessarily justified a library anymore — at least not given the lack of activity around the project.

Continue…

How to start a blog or portfolio website, for developers

01 November 2021
Updated: 05 November 2021

Ever so often an iOS developer asks me how to get started with making their own blog or portfolio website. Or, I’ll see a software developer from another community on Twitter ask the same thing. Often they are earlier in their career, or unfamiliar with web development, or unsure whether to build from scratch or use a platform, or all of the above. I find myself consistently making the same recommendations to folks. For this post, I want to share what I think is a great approach to get started, and how you can dive deeper once you master the basics.

Continue…

Recently updated posts

22 October 2021

Periodically, I go back to add updates to older posts. I’ve been doing this for some time now, although not as often as I would like. I aspire to be as good and diligent as Michael Tsai, but that’s an incredibly high bar. (How does he do it?!)

Continue…

An iOS shortcut to show proof of vaccine

12 September 2021
Updated: 07 October 2021

Here in Oakland and the rest of the Bay Area, more and more restaurants, bars, venues, and various events are requiring that people show proof of vaccine before entering. (As it should be.) Thankfully, all businesses and events allow showing proof digitally rather than carrying around your physical COVID-19 Vaccination Record Card from the CDC. This means you can take a photo with your phone and present that instead of your singular paper copy. This is great, but the tediousness of tapping around my phone to find and display it has been annoying. So, I made an iOS shortcut to present it instantly.

Continue…

Useful label-based GitHub Actions workflows

24 August 2021
Updated: 21 March 2022

My current team has started using GitHub Actions to automate some tedious tasks for pull requests. In particular, we use labels on GitHub to categorize pull requests or highlight important metadata about them. Most of the time, a machine can figure out which labels are appropriate to add or remove. This is a great use case for GitHub Actions.

Continue…

Different ways to observe properties in Swift

08 August 2021

After I wrote and released Foil, my library for implementing a property wrapper for UserDefaults, one of the criticisms on Twitter was that a mechanism for observing such properties should have been included. I disagreed. In the post I argued that this was easy enough for clients to handle on their own, but more importantly that there are too many options for how to do this and I didn’t think Foil should impose any one of them on clients.

Continue…

Fixing a hard-to-find bug in Dark Mode

15 July 2021

I previously wrote about implementing Dark Mode in an older codebase, specifically how Dark Mode works (or doesn’t) with CGColor. I recently fixed a bug in the same project that was difficult to track down because it manifested in such a strange way. After finding the problematic code, I realized that it is an extremely common scenario in iOS codebases — so you might have this bug in your code as well!

Continue…

Debugging a DiffableDataSource CellProvider

11 July 2021

I was recently working on a project that uses modern collection views on iOS — that is, using diffable data sources, snapshots, and cell providers. I hooked up all the components and my collection view was working, or so I thought. I started to notice some very odd, unpredictable behavior when the collection view was updated. Some of the time, the cells were updated correctly. Other times, I would see duplicates and missing data. Here’s what went wrong.

Continue…

Is SwiftUI ready?

01 July 2021
Updated: 08 October 2021

I’ve been following what’s going on with SwiftUI since it was released with iOS 13 at WWDC 2019 and have even taken extensive notes, but I have avoided using it. As I wrote before, I mainly wanted to avoid dealing with bugs and workarounds that might make me less productive compared to using UIKit, which I know quite well. I’m very interested in learning and using it, I’m just hesitant given some of Apple’s history, like early years of Swift. I have no doubt that SwiftUI will be the future of Apple platform development, the question is when that future will arrive. This year the framework is debuting its third major release in iOS 15. How far has SwiftUI come, and is it ready for building serious apps?

Continue…

RSS feeds, Jekyll, and absolute versus relative URLs

06 June 2021
Updated: 09 June 2021

Lately I’ve been upgrading and making improvements to my website and blog. As part of that work, I was updating and refining how my RSS feed gets generated with Jekyll. And then I realized something that I had not given much thought to previously. When including the full content of blog posts in an RSS feed, if you link to other posts or pages on your site should you be using absolute URLs or are relative URLs ok?

Continue…

To distribute in the Mac App Store, or not

Is the app sandbox worth it? 02 June 2021

For the past few weeks I have been debating on whether or not to distribute a new Mac app via the Mac App Store or independently. I have arrived at a crossroads in development where I need to make this decision. I am mostly code-complete for my MVP 1.0 release. The question I am facing is how I want to spend the remainder of my time to cross the finish line.

Continue…

iOS 14 App Library

01 June 2021

I think App Library is one of the best features added to iOS in the past few years. I’m not being sarcastic, I know some folks dislike it. However, I absolutely loathe trying to organize apps on my phone into folders, because many apps do not have a singular, definitive category.

Continue…

Three months of Big Sur

01 June 2021
Updated: 09 June 2021

I upgraded to Big Sur three months ago. I know I’m (fashionably?) late to this party, but here I am. This is the longest I have ever waited to upgrade macOS. It feels weird, considering WWDC is next week where we will see what is next for macOS. Big Sur still feels new to me, and announcing the next major release already feels too soon. I was avoiding Big Sur based on various reports about bugs and instability. There were not any ‘killer’ features I was eager to have, thus the main reason I upgraded was because Xcode 12.5 required it.

Continue…

Resources for learning SwiftUI

07 April 2021

A few months ago, I shared my notes and resources for learning about compilers and LLVM. It turned out to be pretty popular and folks seemed to find it useful. So I decided to do it again, but this time for SwiftUI. However, unlike learning about compilers and LLVM, I am not declaring bankruptcy with learning SwiftUI. While I have still not written a single line of SwiftUI code, I know I eventually will.

Continue…

Migrating OmniFocus to a new Mac

31 March 2021

One aspect of using OmniFocus involves maintaining an archive of your data (if you choose). Over time — think years of using OmniFocus as your main task management tool — your local database of projects and tasks will grow very large, because OmniFocus keeps a record of everything you have completed or dropped. You can think of it as archiving your emails instead of putting them in the trash.

Continue…

Returning to normal, Part 3

23 March 2021
Updated: 24 March 2021

After only five days, yet another mass shooting has happened in the US. This post follows Part 1 and Part 2 in this ongoing series documenting how the US is recovering from a life-threatening virus.

Continue…

Xcode tips for everyone

22 March 2021

Lately, it feels like every few days someone is sharing a new Xcode tip on Twitter or on their blog. They range from hidden settings to features I simply never knew about. I started saving links and planned to add a new “Xcode tips” section to my TIL repo on GitHub to reference later. But as I started, I realized that the resulting markdown file would not be easily discoverable or shareable. I thought, wouldn’t it be nice if the iOS and macOS developer community had a single place to find and share Xcode tips?

Continue…

Using pipes in Swift scripts

18 March 2021
Updated: 22 March 2021

I have a few Swift scripts to automate tedious tasks for maintaining my blog. I updated one today to use pipes. It took me a minute to figure out, because it did not feel very intuitive. I’m not sure if I feel that way because the interface is actually that clunky, or if I’m just inexperienced with Swift scripting. In any case, here’s how it works.

Continue…

Xcode UI testing reliability tips for iOS

17 March 2021
Updated: 18 March 2021

Xcode’s UI testing framework has had its ups and downs over the years. Most recently, it has been much more robust and reliable in my experience. However, tests still tend to flake sometimes. Here are some ways that I have been able to reduce flakiness in UI tests.

Continue…

Returning to normal, Part 2

17 March 2021

I did not expect that I would have to follow-up on yesterday’s essay so soon, but I can’t say I’m surprised. In the past 24 hours, there were two mass shootings in the US. It is shocking and horrifying, yet somehow entirely predictable.

Continue…

Deleting tweets and other social media content

16 March 2021

I have been periodically deleting my tweets for a while now. Yesterday, I finally found a reliable solution for deleting my Twitter “likes” as well and I spent some time deleting all of them. Long ago, I also deleted all of my content on Facebook and Instagram. If you are interested in purging your social media accounts, here are some options.

Continue…

Returning to normal

16 March 2021

Oakland has been anything but normal over the past year during the pandemic. But we are starting to see glimpses of normality. Little by little, the whole country is returning to “business as usual”, as they say. And the first real indication that normality is on the horizon for the US was a recent story out of Arkansas.

Continue…

A list of books I read in 2020

30 December 2020

Continuing my (still somewhat recent) tradition, here are the books I read in 2020. You can find previous years under the #reading-list tag. I really thought I was going to be able to read a lot more this year, but fuck this pandemic and fuck 2020 all around. There were many weeks where I simply could not focus on much of anything.

Continue…

Resources for learning about compilers and LLVM

28 December 2020

Today I cleaned up my various projects and todo’s in OmniFocus. I am always collecting links and resources for potential project ideas, or for general learning. Sometimes, however, it is best to acknowledge that I will likely never have enough free time to even begin some of these endeavors.

Continue…

What type is self in a Swift self-executing anonymous closure used to initialize a stored property?

The answer might surprise you 22 December 2020
Updated: 02 March 2022

In JavaScript, this pattern is called an Immediately Invoked Function Expression (IIFE) or a Self-Executing Anonymous Function. Swift doesn’t have an “official” name for this, but IIFE works as well as “immediately executed anonymous closure” or “self-executing anonymous closure”. (Thanks to folks on Twitter for helping with this.)

Continue…

Obscure bridgeOS crash

22 December 2020

This is a first for me. I returned to my MacBook after leaving it for a couple of hours, and it was shutdown even though I left it powered on. The machine was idle. I didn’t have any specific tasks running. I figured it might have been a macOS kernel panic, but upon rebooting I discovered that the crash was caused by bridgeOS.

Continue…

Useful Danger rules for Bitrise

20 December 2020

This is a quick follow-up to my previous post. The client project I’m working on is also using Bitrise for CI, which I must say is quite good. If you are looking for a hosted CI service I would highly recommend checking them out.

Continue…

Running multiple instances of Danger

15 December 2020

For a client project that I’ve been working on, I recently integrated Danger to automate pull requests for the team. I initially setup a single Dangerfile to run on CI, but soon after we had the need to split it up in order to run danger more than once for a single CI run.

Continue…

Radical readings for the Tech Worker

26 November 2020

After reading my recent satire piece, a good friend of mine (and tech worker) asked if I had a list of books or other resources to learn more about labor history and capitalism in the United States, and how the tech industry operates in this broader context. I had been meaning to write about this, and I figured others would likely be interested, too. So, if you are interested in these topics then this is post for you!

Continue…

Seasons Greetings from your CEO at TECH COMPANY

An email from your boss's boss's boss 24 November 2020

Dear COMPANY NAME team:

Hello employees — or should I say independent contractors?! (More on that shortly.) I’m writing to you from my second mansion located in ECONOMICALLY DESTABILIZED COUNTRY IN THE GLOBAL SOUTH EXPLOITED BY UNITED STATES IMPERIALISM! I see the poor children here, and it just reminds me how privileged all of us are to live in a virtuous place like Silicon Valley (at least when I’m there, lol) where we pretend homeless people simply don’t exist. And if they do, it’s because they didn’t try hard enough to do a startup or they didn’t have enough generational wealth to do financial crimes.

Continue…

Swift deinit is (sometimes) not called for throwing or failable initializers

08 October 2020

I was never a fan of failable initializers in Swift. I do not think this is the correct place to fail and return nil most of the time. Of course, there are exceptions where a failable initializer is appropriate. But there is another behavior of which to be aware. When constructing a class via a failable initializer, init?() — or a throwing initializer, init() throws — the deinitializer, deinit, is not called if initialization fails or throws, respectively.

Continue…

Don't forget the keyboards

An essay 15 September 2020

You know, the thing that is actually most disheartening, disappointing, frustrating, and plainly sad about Apple’s surprise announcement today is that we will not receive any sort of response to our collective dismay. There will be no public acknowledgment, much less an apology (not that it would help much). Only silence.

Continue…

Unpropertied

30 August 2020

I’m currently reading Marquis Bey’s Anarcho-Blackness: Notes Toward a Black Anarchism. These are some reflections on and excerpts from the fourth chapter, titled Unpropertied. This post comes against the backdrop of continued protests and uprisings here in Oakland and the rest of the Bay Area in solidarity with Minneapolis, Kenosha, and the broader fight against police violence.

Continue…

How to fix the incomprehensible tabs in Xcode 12

24 July 2020
Updated: 06 October 2020

Xcode 12 was released and it includes a change to how tabs and navigation work. In Xcode 12, the tabs have their own tabs. It makes no sense to me. I know we are supposed to be nice to each other about software, but this new UI/UX is beyond incomprehensible. What made it worse is that this new “tabs within tabs” was the default setting (overriding preferences I had previously set) and I could not figure out how to restore the previous (desired) behavior.

Continue…

Swift globals and static members are atomic and lazily computed

16 July 2020

While debugging some code the other day, I wanted to verify the behavior of global variables and static members in Swift. I vaguely remembered from the early days of Swift, that static let members and global constants were atomic and computed lazily — one of the many improvements over Objective-C.

Continue…

The best Touch Bar configuration for people who hate the Touch Bar: Or, how I finally upgraded my 6-year-old MacBook

08 July 2020

I like to keep my devices for a long time — as long as possible, actually. I do not need (nor want) a new iPhone and MacBook every year, or even every other year. (Or more!) Putting Apple’s issues aside, the company is quite good at keeping old hardware running the latest software, and generally their hardware is very high quality (except for the utter clusterfuck that was “keyboard gate”). I find it pretty easy to keep devices for 4-6 years, if they are taken care of.

Continue…

Quickly switching between Xcodes

07 July 2020
Updated: 22 August 2021

I try to have only one Xcode installed at a time for simplicity and tidiness. But such a setup is rare as we often must manage stable releases and beta versions simultaneously.

Continue…

Who do they protect?

An essay on police brutality in America 17 May 2020

I am infuriated. Yesterday morning I woke up to the news that in my hometown of Louisville, KY Breonna Taylor was murdered by the police while she was sleeping. Because she was Black. She was shot 8 times. I do not need to list the names of every innocent and unarmed (or sleeping!) Black human being who has been murdered on the streets or in their own homes by the police in this country. You already know them. This has happened so many times before, from the lynchings in the 1800s to LA in 1992 to Louisville today.

Continue…

On non-native apps: JavaScript doesn't suck but your app might

16 May 2020

The other day Slack went down and I tweeted to express my dissatisfaction and sarcastically comment that non-native apps are the future. I should have known it would get as much attention as a tweet about Elon Musk. People argued about the merits of native versus non-native app development, which seems like a never-ending a controversy. However, I really do not care which technologies are used to make an app. I only care about the quality of an app and the user experience it provides — which is the problem with Slack.

Continue…

Simple, private, and open source analytics with GoatCounter

08 May 2020

I removed Google Analytics on this site over two years ago. It was doing more harm than good. I did not want to jeopardize readers’ privacy. I did not want to be part of the bullshit web. I did not want to contribute to Google’s massive data collection and its take over of the open web. I did not want to be Google’s product. (Because fuck Google.)

I rarely even looked at those analytics back then. However, since going independent last year, I have more interest in knowing and understanding the traffic on this site. I found a fantastic solution for analytics that is simple, private, and open source called GoatCounter.

Continue…

Implementing Dark Mode and using CGColor

23 March 2020

For an iOS project that I am currently working on, I am implementing Dark Mode. The codebase is approaching 7 years old, it is mostly Swift with some legacy Objective-C, and it currently supports iOS 11 and above. Aside from the tedium of ensuring the updated colors are being used throughout the codebase, I expected this task to be straight-forward. However, there were some unanticipated issues.

Continue…

Mac app tests fail with hardened runtime enabled

23 February 2020

I recently discovered that unit tests and UI tests for a macOS Xcode project will fail with obscure error messages if the hardened runtime is enabled. It took me awhile to realize what the actual source of the problem was, because the error messages led me in the wrong direction. Hopefully this will save you some time.

Continue…

Setting up default community health files on GitHub and crafting a thorough Contributing Guide for any open-source project

24 January 2020

Every open-source author, maintainer, and contributor knows the importance of fostering a positive environment for collaboration and providing adequate resources for folks to seek help and contribute in a meaningful way. These resources include providing a Code of Conduct, a Contributing Guide, issue templates, and more. GitHub refers to this collection of documents as community health files, and they have been slowly improving their support for them. I recently spent some time creating defaults for these files, including crafting a completely new Contributing Guide for all of my projects.

Continue…

Xcode tip: Using breakpoints as bookmarks

21 January 2020
Updated: 11 July 2023

Xcode has a great UI for setting and editing breakpoints. I use breakpoints all the time while working and debugging, but I want to share another, unconventional way that I use them.

Continue…

AppleScript to export open Safari tabs to OmniFocus

14 January 2020

I love OmniFocus. It is an indispensable app for me and a great Mac app. For managing and organizing to-do lists and personal projects, there is nothing better. Being a great Mac app means adopting behaviors that users expect, conforming to macOS UI/UX paradigms, and for the truly great mac apps it means being scriptable. I want to share two AppleScripts that I wrote for OmniFocus to automate one of my common workflows.

Continue…

Observing appearance changes on iOS and macOS

08 January 2020

I recently needed to determine when the user has manually switched between dark mode and light mode on macOS. In my menu bar app, Lucifer, the icon reflects the current appearance setting when you change it from the app — an inverted pentagram for dark mode and an upright pentagram for light mode. But there’s a bug. If the user manually changes the appearance setting from System Preferences, or if they are using the new “auto” setting in macOS Catalina, the icon gets stuck in its previous state.

Continue…

Selecting an Xcode version on GitHub Actions CI

06 January 2020

I have started using GitHub Actions for CI on a new project as a replacement for my usual setup on Travis CI. It generally seems to be much faster and more reliable so far. It also has an equivalent feature set, as far as I can tell. But one issue that I have run into is selecting a specific Xcode version, which is a bit cumbersome and not fully documented.

Continue…

Backing up your iCloud Drive files using rsync

27 September 2019
Updated: 21 February 2022

Unfortunately, iCloud does not have a good reputation for being reliable, especially during beta releases of iOS and macOS. Yet a lot people still use it, often without any problems. I still use it, despite a few bad experiences in the past, because the best alternatives are questionable for other reasons. I’ve had good luck with iCloud Drive for the past few years, but I am terrified and paranoid of getting caught in the middle of an iCloud clusterfuck, so I backup what I have in iCloud periodically using rsync.

Continue…

Overriding status bar display settings in the iOS simulator

26 September 2019
Updated: 28 September 2019

With version 11 of Xcode, the IDE ships with a new feature in the simctl tool that can override status bar values for iOS simulators. This allows you to take better screenshots for the App Store without having to worrying about the time, battery level, etc. It is a great improvement, but there are some significant shortcomings. I’ve written a script to fix at least some of those.

Continue…

The ACA and your credit report

19 September 2019

As some of you may know, I recently quit my job in San Francisco to pursue personal projects, freedom (sort of) from our collective capitalist nightmare, and self-determination. But I’ll write more on that later. This post is about dealing with health care as an independent software developer in the United States.

Continue…

The impossible

Or, how my Dad just ate an Impossible Whopper and loved it 19 August 2019

I’ve been eating vegetarian (and often vegan) for a decade now. I don’t talk about it much. This is a choice I’ve made for myself and my own reasons. What I never imagined happening is the growing popularity and wide availability of vegan/vegetarian food. It is simply remarkable.

Continue…

Implementing right-click for NSButton

15 August 2019

This isn’t complicated, but I found it confusing. Perhaps I am spoiled by the more modern APIs in UIKit. When writing Lucifer, a menu bar app, I wanted to have different actions for left-clicking and right-clicking on the button in the menu bar. To my surprise, this was much more cumbersome than I expected.

Continue…

Linked Out

Or why I'm getting off of LinkedIn 13 August 2019
Updated: 04 June 2021

I deleted my LinkedIn account, well sort of. I kept my account open, which I will explain below, but I left it mostly empty. You could say I am now officially linked out.

Continue…

Summoning Lucifer: on making my first Mac app as an iOS developer

26 March 2019

I made my first Mac app — Lucifer. It is a menu bar app that allows you toggle Dark Mode on and off in macOS Mojave. To be honest, it feels like a stretch to actually call this a Mac app. It is less than 100 lines of code in a single AppDelegate.swift file and the meat of the program is an AppleScript that tells System Preferences to enable or disable Dark Mode. As an iOS developer, much of the experience was familiar. The most salient aspect, however, was learning the frustrating and obscure details of app sandboxing, the “hardened runtime”, and app notarization — altogether it was like visiting hell and giving Satan a bubble bath. Appropriate, I suppose.

Continue…

Reading Notes: The Individual, Society, and the State

22 March 2019

I intend to start a new series of posts called Reading Notes where I publish notes, excerpts, and thoughts on what I’m currently reading. My goals are to better document my notes and thoughts on what I’m reading for my future self, and give myself a reason to write more blog posts (in general, but also more non-technical ones). I also hope to inspire you, dear reader, to read some of these books and essays.

Continue…

A list of books I read in 2018

05 January 2019

Here’s the list of the books I read in 2018. There are 36 in total. At first it seemed like a small number to me. However, that averages to three books per month, which actually feels like a lot. In fact, I’m not sure I could read more than three books each month. There was never a time last year when I wasn’t reading something, and I often read multiple books at once.

Continue…

Debugging a subtle Swift bug that will make you facepalm

07 November 2018

The other day I was debugging a crash in a UI test for an open pull request at work. The bug turned out to be extremely subtle and difficult to notice. I spent way too much time staring at the changes, trying to understand what was wrong. Let’s see if you can spot the error.

Continue…

Lars And The Basket Of Apples

08 October 2018

There’s a place called North Berkeley Frame in downtown Berkeley on Shattuck. It’s a framing shop and gallery (sort of) run by this guy named Lars. He’s older, probably mid-fifties or early sixties. He has gray hair, a gray beard, and a gentle face. I’ve had him frame some prints and other artwork for me. He’s always helpful in choosing the right frame, and his work is excellent. Like many older folks I know, he loves to talk.

Continue…

15 years later: it was summer and we were free

An essay about loss, recovery, and hope 26 September 2018

Fifteen years ago today my sister died. Most people don’t know about her — Amy. I don’t talk about her much, because talking about death makes people uncomfortable, especially when the loss was so traumatic for those left behind. I was 14, she was 16. It feels like it happened a lifetime ago and that it just happened yesterday, all at once.

Continue…

The Four Agreements

30 July 2018

I haven’t read the book, The Four Agreements, but I will eventually. However, simply knowing what the Four Agreements are has been tremendously helpful for me. They may help you, too. I want to write them down to share, but also to remember them better and have a reference to revisit in the future.

Continue…

Swift tip: Building arrays with compactMap

29 July 2018

A common scenario in app development is to build up a list of objects, perhaps to display to the user or for another purpose. Maybe you’re fetching data from a database to display, or constructing fields to display for an interface. Consider the iOS Calendar app, for example. When you add a new calendar event, the form displays all the fields you can fill-in — title, location, date and time, notes, etc. However, when viewing an existing event all you see are the completed fields while the uncompleted fields are hidden.

Continue…

Hold it! Or, how to blame homelessness on the homeless in San Francisco

An essay on capital and compassion 19 July 2018
Updated: 06 November 2021

The mayor of San Francisco called out feces on the sidewalks as a core problem to address in the city and wants homeless folks to “at least have respect” and “clean up after themselves”. It’s an unfortunate response, but I’m sure a lot of folks agree with the sentiment. No one relishes walking through the dirty streets in this city and it certainly is a concern, but this kind of rhetoric is actively harmful. It deliberately shifts responsibility for the problem onto the victims and away from the system that produced it. Homeless folks are among the most vulnerable in our society. In addition to their lack of housing, persistent precarity, mental health issues, and emotional struggles, the city is now going to ask them for respect and cleanliness?

Continue…

Swift's new calling convention

From callee-owned to guaranteed 05 July 2018

One of the major changes in Swift 4.2 is a change to the calling convention. But what exactly does that mean? Why is it important and why would you want to change it?

Continue…

Choosing a VPN service

24 June 2018
Updated: 08 October 2021

Net Neutrality is officially over in the US. As the EFF notes, it will likely manifest as a slow, painful decline of the Internet. We can call congress to demand that they reverse the decision and act in the interests of the people. But whether or not that succeeds, everyone should be using a VPN regularly now to fight against the growing threats of Internet surveillance and censorship. We know better than to trust corporations and governments.

Continue…

Thoughts on WWDC 2018

Community over technology 11 June 2018

I had a great time at WWDC this year, meeting new friends and catching up with old ones. Those experiences are the ones that matter the most to me. The newly announced tech is interesting and fun, but ultimately fleeting and ephemeral.

Continue…

Why optional closures in Swift are escaping

10 June 2018

In a recent episode of the podcast, JP and I discussed the implicit escaping of closures in Swift. As Swift has matured and evolved, the default behavior of closure parameters in functions has changed. Prior to Swift 3, closures parameters were escaping by default. After SE-103, the default was changed to non-escaping.

Continue…

Upgrading to Bootstrap 4

And some minor design tweaks 16 April 2018

I just updated my blog to use Bootstrap 4.1 from v3.3.7. Its a major version with lots of breaking changes, so it took me a few hours over a few Saturday afternoons to get everything fixed up. That’s also partially why I missed posting something last month.

Continue…

Replacing Google Search with DuckDuckGo

And how to add a custom DuckDuckGo search box to your site 25 February 2018
Updated: 23 October 2021

I’m not interested in being an advertising product for Google to exploit. I’m also not interested in the company’s unsavory practices, in general. I’ve been using DuckDuckGo for over a year now, and I’m incredibly happy with it as a replacement for Google Search — not only for personal usage, but also for implementing a custom search component for this site.

Continue…

How to run sysdiagnose on iOS

And on all the Apple things 08 February 2018
Updated: 05 January 2019

When you file a radar for a bug on one of Apple’s platforms, you should (usually) always attach a sysdiagnose. A sysdiagnose provides a lot of helpful information for the person who is trying to understand how the bug happened. Amongst other things, it contains logs from various parts of the OS, and all recent crash logs. Without it, the person on the other end of your report inside Apple may not be of much help. On macOS running sysdiagnose is somewhat common, but what about iOS?

Continue…

Ending the Swift Weekly Brief

Taking an indefinite hiatus from writing the newsletter, and looking for a new owner 28 December 2017
Updated: 08 February 2018

Next week’s issue of Swift Weekly Brief will be its 100th and final issue. I started this newsletter a little over two years ago, covering the initial open sourcing of Swift, the 3.0 release, the 4.0 release, and many significant milestones in-between for the language and the community. With few exceptions, there was a new issue every week thanks to the other amazing writers and contributors. The newsletter quickly became an important resource for the Swift community. Because of this, I’m sure many of you will be saddened to hear that the 100th issue will be the last. At least, Issue #100 will be the last issue for me, for now — but if someone from the community is willing to take over this project, it can continue.

Continue…

Floating-point Swift, ulp, and epsilon

Exploring floating-point precision 01 October 2017
Updated: 03 April 2023

Epsilon. ε. The fifth letter of the Greek alphabet. In calculus, an arbitrarily small positive quantity. In formal language theory, the empty string. In the theory of computation, the empty transition of an automaton. In the ISO C Standard, 1.19e-07 for single precision and 2.22e-16 for double precision.

The other day I was attempting to use FLT_EPSILON (which I later learned was laughably incorrect) when the Swift 4 compiler emitted a warning saying that FLT_EPSILON is deprecated and to use .ulpOfOne instead. What the hell is ulpOfOne? I read the documentation and then everything made sense — ha, just kidding. The FloatingPoint.ulpOfOne docs generously describe the static variable as the unit in the last place of 1.0 — whatever that means. Let’s find out.

Continue…

When your app is used in unexpected ways

PlanGrid as a digital archaeological tool 24 September 2017

PlanGrid is a productivity app for construction fieldworkers. The easiest way to explain it to software developers is that it’s like an IDE, Git, and GitHub or JIRA — but for construction. Think of all the amazing software tools we have to do our jobs as programmers. The equivalent tools for construction simply did not exist before PlanGrid, and they still have a lot of room to grow.

As software developers, we build software for specific purposes. We anticipate that people will use an app in certain ways. Yet, we often discover that users are behaving differently than we expected. They hack a custom, “unsupported” workflow to workaround an app’s unintended limitations. Once we realize this, we have the power to turn these user workarounds into first-class features. However, sometimes we find that our apps are being used in totally different, unimaginable ways.

At PlanGrid, we recently discovered that the app was being used as a digital archaeological tool.

Continue…

Measuring Swift compile times in Xcode 9

Using -Xfrontend Swift compiler flags 18 September 2017

The Swift type-checker remains a performance bottleneck for compile times, though it has improved tremendously over the past two years. You could even say the type-checker has gone from being drunk to sober. To help users debug these issues, awhile back Jordan Rose added a frontend Swift compiler flag that would emit warnings in Xcode for functions that took too long to compile, or rather took too long to type-check. In Xcode 9, there’s a new, similar flag for checking expressions.

Continue…

Building a site with Jekyll on NearlyFreeSpeech

My blog infrastructure, and migrating off of GitHub pages 10 September 2017
Updated: 07 October 2020

This site used to be hosted via GitHub Pages, but I decided to move to a dedicated host to have more control over how I develop and deploy the site, and how it’s configured. A number of limitations and quirks eventually drove me to migrate away from GitHub pages to my excellent and inexpensive bare-bones host, NearlyFreeSpeech.net. I was also interested in learning to do all of this on my own, rather than relying on GitHub Pages “magic”. If you’re looking to setup your own Jekyll-powered site, or if you’re looking to migrate off of GitHub Pages, hopefully this is helpful.

Continue…

Supporting JSON feed

Now available 03 September 2017

A couple of weeks ago I finally got around to adding support for Brent Simmons’ and Manton Reece’s JSON Feed for this blog. You can subscribe to the feed here. It was simple and fun to implement.

Continue…

Data & Society: Media Manipulation and Disinformation online

New report from the Data & Society Research Institute 13 August 2017

Data & Society recently released a stunning report, Media Manipulation and Disinformation Online. I highly suggest you read it if you care about understanding the rise of neo-fascism, the ‘fake news’ phenomenon, and manipulation of the media that plagued the 2016 US Presidential Election — and how Silicon Valley, particularly social media platforms, facilitated the rise of the alt-right movement and the spread of fascist propaganda. Don’t let the more than 100 pages deter you. The core report is only 50 pages, followed by a few pages of case studies, and finally a whopping 45 pages of citations and bibliography. (Direct download)

Continue…

Customizing git-log

Creating a 'smartlog' alias in git 08 August 2017

Git is sometimes rough around the edges, but fortunately it’s not too difficult to customize and make more user-friendly. The other day I spent some time experimenting with git log and crafting a new git smartlog alias.

Continue…

A story about Swift source compatibility

How to add your projects to the swift-source-compat-suite and why you should 17 July 2017

The Swift community has been through some rough migrations. It is frustrating when your project no longer compiles because of API and syntax changes, but it is an entirely different story when your project seg faults the compiler. When that happens, you cannot simply run a migration tool or apply fix-its — your project is broken and there’s little you can do until a fix is released. This is why the swift-source-compat-suite project was created.

Continue…

Officially deprecating JSQMessagesViewController

No longer maintaining or supporting this project 16 July 2017
Updated: 18 July 2017

Beginning immediately, JSQMessagesViewController is no longer officially supported or maintained. In fact, you may have noticed that it has been neglected for the past year. The most recent release was published almost exactly one year ago today. This is an incredibly difficult post for me to write and I have not made this decision carelessly. This open source project had a great run. There was (and still is) a great community around it, and I’m sorry for bringing this to an end.

Continue…

Protocol composition in Swift and Objective-C

Designing optional semantics without optional methods 05 June 2017

Protocols in Swift and Objective-C are a powerful tool to decouple your code. They allow you to specify a contract between classes that consume them, but defer a concrete implementation to conformers. They allow you to segregate interfaces and invert control. One interesting aspect of protocols in Swift and Objective-C is that protocol members can be optional (optional in Swift or @optional in Objective-C). Unfortunately, this comes with a number of disadvantages and diminishes the robustness of your code, so it is often avoided. However, having optional members is sometimes the right conceptual model for your design. How can you design your protocols to provide optional semantics without specifying them as optional or @optional?

Continue…

Writing better singletons in Swift

Avoiding common pitfalls 04 June 2017

In a previous post I discussed strategies for using singletons in a cleaner, more modular way. Singletons are a fact of software development, especially in iOS. Sometimes the design pattern actually is the right tool for the job. In those situations, how we can improve the way we write our own singleton classes?

Continue…

A Fair Hotel

Choosing a place to stay for your next conference 28 May 2017

Earlier this week, the Tech Workers Coalition and UNITE HERE! in San Francisco hosted a panel discussion on how we can use our power as consumers to support hotel workers in the Bay Area and across the United States. The tech industry is full of remote workers, as well as conference organizers that host thousands of conferences each year — meaning thousands of programmers, designers, product managers, and others travel all the time to attend these conferences or attend their own company’s events. By choosing to stay at a fair hotel, you can make a significant impact on an industry where workers are struggling to negotiate fair wages and benefits.

Continue…

Swift Unwrapped

Co-hosting a new podcast with JP Simard 07 March 2017

A few months back, JP Simard and I decided to start a podcast about Swift — the language itself, its evolution and development, the Swift.org open source projects, and general Swifty news. There are a ton of great podcasts out there about developing for Apple platforms and Apple news, but there’s nothing exclusively about Swift the language. In many ways, this podcast is an extension of and commentary on the Swift Weekly Brief newsletter. However, we’ll be doing deep dives on various topics and elaborating on concepts in greater detail. I’m excited to share that we launched Swift Unwrapped yesterday with Spec.fm!

Continue…

Refactoring singleton usage in Swift

Tips for a cleaner, modular, and testable codebase 10 February 2017

In software development, singletons are widely discouraged and frowned upon — but with good reason. They are difficult or impossible to test, and they entangle your codebase when used implicitly in other classes, making code reuse difficult. Most of the time, a singleton amounts to nothing more than a disguise for global, mutable state. Everyone knows at least knows that is a terrible idea. However, singletons are occasionally an unavoidable and necessary evil. How can we incorporate them into our code in a clean, modular, and testable way?

Continue…

Sleazy recruiting

LAMP stack for an iOS developer 09 February 2017

Today I found out that I’m part of a class action lawsuit against a service that I never signed up for called TalentBin. As you have likely experienced, most recruiting in the tech industry is debase, disingenuous, boilerplate garbage. But this — this is definitely a new a low.

Continue…

Pushing the limits of protocol-oriented programming

Talk at Swift Summit in San Francisco 23 January 2017

A few months ago, I spoke at Swift Summit in San Francisco. The conference has a reputation for providing high-quality talks, and this year was no different. Fortunately, I was able to see nearly all of the talks and not a single one disappointed me. It was such a great conference. The video and full transcript of my talk are now available. The videos of the other talks will be coming online over the next few weeks. I would recommend watching all of them!

Continue…

Testing and mocking without OCMock

For Swift and Objective-C 16 January 2017

OCMock is a powerful mock object unit testing library for Objective-C. Even if you are using Swift, as long as your classes inherit from NSObject, you can use some of its features. But what if you are writing pure Swift code which does not have access to the dynamic Objective-C runtime? Or, what if you don’t want your Swift code to be hampered by NSObject subclasses and @objc annotations? Perhaps, you merely want to avoid dependencies and use ‘plain old’ XCTest with Objective-C. It’s relatively easy and lightweight to achieve the same effect in some testing scenarios without using OCMock.

Continue…

Shipping Swift 3.0

An update on my open source libraries 01 October 2016

I’m happy to share that all of my open source Swift libraries have (finally) been updated for Swift 3. If you’ve been waiting for any of these final releases, you can now run pod update or carthage update and relax — sorry it took so long! I wrote about migrating to Swift 3 a few months ago and this post shares the final results of the process that I outlined in there.

Continue…

Speaking at FrenchKit

Paris, France 30 September 2016

Last week I attended and gave a talk at FrenchKit in Paris, France. As expected, it was an amazing conference — especially considering it was the first FrenchKit ever. I think the organizers are already thinking about FrenchKit 2017, so keep an eye out and definitely go if you can. I know I will.

Continue…

Enums as configuration: the anti-pattern

Implementing the open/closed principle 31 July 2016

One of the most common patterns I see in software design with Objective-C (and sometimes Swift), is the use of enumeration types (enum) as configurations for a class. For example, passing an enum to a UIView to style it in a certain way. In this article, I explain why I think this is an anti-pattern and provide a more robust, modular, and extensible approach to solving this problem.

Continue…

Migrating to Swift 3

Advice, tips, and warnings 25 July 2016

I spent most of my free time last weekend and a few days of last week on migrating my Swift code to Swift 3.0 — I migrated my open source projects as well as my private side projects. Overall, I would say my experience was “OK”. It definitely could have been better, but I think the largest problem was overcoming the cognitive hurdle of seeing all the changes and errors from Xcode’s migration tool at once. The best thing to do is wipe away the tears, put your headphones on, and start hacking. 🤓

Continue…

Swift 3 sherlocked my library

Many of our "Swifty" wrappers are no longer necessary 03 July 2016

What’s my favorite thing about Swift 3? Not maintaining third-party libraries that make Cocoa more “Swifty”. Swift 3 sherlocked my libraries, and I couldn’t be happier.

Continue…

The A5 is dead (almost)

iOS 10 drops support for A5 devices 14 June 2016

As developers, we’ve been lamenting the continued existence of the inferior A5 system-on-a-chip for the past couple of years. Both iOS 8 and iOS 9 continued to support iPhone 4S, iPad 2, and iPad Mini 1 — devices that struggled to run the OS itself. I had hoped that iOS 9 would finally drop support for these less powerful devices, but it didn’t. Today, we can finally say goodbye to the A5. Well, almost.

Continue…

Avoiding the overuse of @objc in Swift

Don't let Objective-C cramp your style 04 June 2016

A few days ago I was (finally!) updating a project to use Swift 2.2 and I ran into a few issues when converting to use the new #selector syntax introduced by proposal SE-0022. If using #selector from within a protocol extension, that protocol must be declared as @objc. The former Selector("method:") syntax did not have this requirement.

Continue…

Open source everything

Getting meaningful contributions to move your projects forward 22 May 2016

I recently had an incredible experience with one of my open source projects that I’d like to share. It’s a story of openness and collaboration that I hope other open source project maintainers will find valuable. This post continues the theme of “building successful open source projects” from my previous article on documentation.

Continue…

Swift documentation

Writing, generating, and publishing great docs in Swift 20 May 2016
Updated: 18 April 2018

The Swift community is ecstatic about Swift. There are so many new libraries being released each week that some have created package indexes — even IBM. But of course, a library is only as great as its documentation.

Continue…

Call for contributors

Join the JSQMessagesViewController team! 06 February 2016

Do you love writing code? Are you passionate about open source? Do you want to get more involved, but have yet to find a project to which you want contribute? Are you interested in contributing to a widely used, impactful project? Then I have a proposition for you! I am looking for dedicated core contributors to help maintain JSQMessagesViewController!

Continue…

The new weekly brief

The Swift Weekly Brief gets a new home 14 January 2016

In case you are late to the party, I finally found some time to give the Swift Weekly Brief a proper home. Starting this newsletter kind of happened by accident when I first wrote about the Swift open source announcement. Since then, it was kind of bootstrapped here on my personal blog and started to feel awkward. I hacked together the new site in a couple of nights and moved all the previous posts over. Today’s issue #5 is the first one to be originally published at swiftweekly.github.io. However, there is more here than just organization and a nice separation of concerns.

Continue…

Open source Swift: weekly brief #4

What's been happening on Swift.org? 07 January 2016

Now that the holidays are over, things have started to pick up again on Swift.org. If you are following any of the repos on GitHub, you have probably noticed. I’m not sure how I missed this before, but this week I just discovered SwiftExperimental.swift. For now, it defines a bunch of custom unicode operators for Set. It’s really cool. I would love to see more APIs like this in the standard library. Anyway, here’s the weekly brief!

Continue…

Open source Swift: weekly brief #3

What's been happening on Swift.org? 24 December 2015

As expected with the holiday season, things are slowing down for a bit on Swift.org. I have been traveling for the holidays as well, so this issue will be shorter than usual. If you haven’t already, be sure you take some time away from coding to enjoy the holidays and avoid burnout. Now, the weekly brief!

Continue…

Open source Swift: weekly brief #2

What's been happening on Swift.org? 17 December 2015

The Swift.org community is finishing up its second full week of open source development. If you were hoping for a quiet week, you will definitely be disappointed. There is still a ton of activity with no signs of slowing down. The Swift team continues to work openly and to be encouraging to contributors. This week brought more crash fixes and more Swift Evolution proposals. Let’s get to it — the weekly brief!

Continue…

Open source Swift: weekly brief

What's been happening during the first full week on Swift.org? 10 December 2015

It looks many developers in the community enjoyed my previous post detailing my thoughts and observations on the activity around the Swift open source project. So, I’m going to try to do this weekly — every Thursday, since the open source announcement was on a Thursday. Each week I’ll provide a high-level summary of what’s been happening, updates on interesting statistics, and links to interesting content. If you have any suggestions, please let me know! And now, the weekly brief!

Continue…

Swift open source

Let the revolution begin 06 December 2015

It has only been a few days since the announcement of Swift going open source and the activity around the project has been incredible. When Apple revealed that Swift would be open source at WWDC earlier this year, I do not think anyone anticipated a release like this.

Continue…

Building type-safe, composable data sources in Swift

A modern approach to collection views and table views 25 October 2015

In iOS development, the core of nearly every app rests on the foundations provided by UICollectionView and UITableView. These APIs make it simple to build interfaces that display the data in our app, and allow us to easily interact with those data. Because they are so frequently used, it makes sense to optimize and refine how we use them — to reduce the boilerplate involved in setting them up, to make them testable, and more. With Swift, we have new ways with which we can approach these APIs and reimagine how we use them to build apps.

Continue…

Swift enumerations and equatable

Implementing equatable for enums with associated values 26 July 2015
Updated: 03 January 2021

Recently, I came across a case (pun intended) where I needed to compare two instances of an enum type in Swift. However, it was an enum where some cases had associated values. At first glance, it is not obvious how to do this.

Continue…

Namespaced constants in Swift

Using nested types for clarity 19 July 2015
Updated: 23 July 2015

Mike Ash has a great Friday Q&A on namespaced constants and functions in C. It is a powerful and elegant technique to avoid using #define and verbose Objective-C prefixes. Although Swift types are namespaced by their module, we can still benefit from implementing this pattern with struct and enum types. I’ve been experimenting with this approach for constants in Swift and it has been incredibly useful.

Continue…

Using Core Data in Swift

Talk at Realm in San Francisco 25 May 2015

I recently gave a talk at the Swift Language User Group (#SLUG) meetup at Realm in San Francisco. A video of the talk is now online over at Realm’s blog, where it is synced up with my slides. If you haven’t already seen it, go check it out! Realm does an absolutely amazing job with posting these meetup talks — in addition to the video and slides, there’s a full transcript and subtitles.

Continue…

Failable initializers, revisited

Functional approaches to avoid Swift's failable initializers 06 April 2015

In a previous post, I discussed how Swift’s failable initializers could be problematic. Specifically, I argued that their ease of use could persuade or encourage us to revert to old (bad) Objective-C habits of returning nil from init. Initialization is usually not the right place to fail. We should aim to avoid optionals as much as possible to reduce having to handle this absence of values. Recently, @danielgomezrico asked a great question about a possible use case for a failable initializer — parsing JSON. Given this problem’s popularity in the Swift community, I thought sharing my response here would be helpful.

Continue…

Functional notifications

Exploring the flexibility of Swift micro-libraries 31 March 2015

The observer pattern is a powerful way to decouple the sending and handling of events between objects in a system. On iOS, one implementation of this pattern is via NSNotificationCenter. However, the NSNotificationCenter APIs are kind of cumbersome to use and require some boilerplate code. Luckily, Swift gives us the tools to improve NSNotificationCenter with very little code.

Continue…

Better Core Data models in Swift

How Swift can bring clarity and safety to your managed objects 17 February 2015

As I continue my work with Core Data and Swift, I have been trying to find ways to make Core Data better. Among my goals are clarity and safety, specifically regarding types. Luckily, we can harness Swift’s optionals, enums, and other features to make managed objects more robust and more clear. But even with the improvements that Swift brings, there are still some drawbacks and limitations with Xcode’s current toolset.

Continue…

Swift, Core Data, and unit testing

Working around Swift's constraints to unit test models 05 January 2015

Core Data is probably loved as much as it is shunned by iOS developers. It is a framework of great power that often comes with great frustration. But it remains a popular tool among developers despite its pitfalls — likely because Apple continues to invest in it and encourages its adoption, as well as the availability of the many open-source libraries that make Core Data easier to use. Consider unit testing, and Core Data gets a bit more cumbersome. Luckily, there are established techniques to facilitate testing your models. Add Swift to this equation, and the learning curve gets slightly steeper.

Continue…

Introducing JSQMessagesVC 6.0

A brief history and celebration of the popular messages UI library for iOS 08 December 2014

A few weeks ago I published the sixth major release of my our messages UI library for iOS. This release closes the door on a major milestone for this project, so I wanted to take the time to highlight its significance, discuss its new features, and examine its design. Of course, this would not have been possible without our amazing open-source community and the contributors to this project.

Continue…

Rosetta Stone contributes

Rosetta Stone officially joins the open-source community 05 December 2014

I’m incredibly happy and incredibly proud to share that Rosetta Stone is an open-source software contributor. Since I started working at Rosetta Stone a little more than a year ago, I’ve been encouraging and advocating for the company to get involved in open-source. Today, we did just that. Today is a big day for Rosetta Stone.

Continue…

Swift failable initializers

When failable becomes fallible, and how to avoid it 22 October 2014

Swift is still young and ever-changing. With each release, we have seen dozens of tweaks, additions, and deletions. And there is no reason for us to think that this rapid evolution will decline anytime soon. To remind us of exactly that, the latest post on Apple’s Swift Developer Blog introduces a new feature in Swift 1.1 in Xcode 6.1failable initializers.

Continue…

Adaptive user interfaces

Exploring iOS size classes and trait collections 01 October 2014

When the App Store launched, there was one iPhone with one screen size and one pixel density. Designing your user interfaces was relatively simple and the technical debt of hard-coding them was cheap. Today, developers and designers face many challenges in creating apps that must work on dozens of different devices. Long gone are the days of 480x320. We can no longer depend on physical screen sizes and must always be prepared for the next generation of devices.

Continue…

Apples to apples, Part III

A modest proposal: can Swift outperform plain C? 21 August 2014

When I find my code is slow or troubled, friends and colleagues comfort me. Speaking words of wisdom, write in C. It is understood that foregoing the features and abstractions of high-level programming languages in favor of their low-level counterparts can yield faster, more efficient code. If you abandon your favorite runtime, forget about garbage collection, eschew dynamic typing, and leave message passing behind; then you will be left with scalar operations, manual memory management, and raw pointers. However, the closer we get to the hardware, the further we get from readability, safety, and maintainability.

Continue…

On the value of benchmarks

A brief examination of measuring code performance 19 August 2014

As Apples to apples, Part II made its way around the web, it was praised as well as critiqued. The latter largely consisted of questions regarding the real-world applications of these benchmarks. In general, benchmarks should be taken with a grain of salt. I want to take a minute to clarify my thoughts on benchmarks and how I think they can be valuable.

Continue…

Apples to apples, Part II

An analysis of sorts between Objective-C and Swift 06 August 2014

If at first you don’t succeed, try, try again. Practice makes perfect. These proverbs have encouraged us all in many different contexts. But in software development, they tug at our heartstrings uniquely. Programmers persevere through countless nights of fixing bugs. Companies march vigilantly toward an MVP. But after 1.0 there is no finish line, there is no bottom of the 9th inning. There are more bugs to be fixed. There are new releases ahead. The march continues, because software is not a product, it is a process.

Continue…

Status bars matter

Perfecting your app screenshots for the App Store 03 August 2014
Updated: 13 October 2014

You have spent countless hours, days, months, or maybe even years perfecting your app. There has been plenty of blood, sweat, and tears. Your relationships and your health have suffered through the development process. You are ready for 1.0 and the time has arrived to prepare all of your content for the App Store — app icon, keywords, description, localizations, and screenshots (and soon app previews).

Continue…

Apples to apples

A comparison of sorts between Objective-C and Swift 25 June 2014
Updated: 01 August 2014

When Craig Federighi arrived at his presentation slide about Objective-C during this year’s WWDC keynote everyone in the room seemed puzzled, curious, and maybe even a bit uneasy. What was happening? As he continued, he considered what Objective-C would be like without the C, and the room abruptly filled with rumblings and whispers [1] as developers in the audience confided in those around them. If you had been following the discussions in our community about the state of Objective-C (and why we need to replace it) during the previous months, you could only have imagined one thing: Objective-C was no more — at least not as we knew it.

Continue…

Built with open-source

The beginnings of this blog 09 June 2014

XKCD’s posts on saving time and automation are precisely how this blog came to be. Until now, I never had the time or motivation to write on a regular basis, though I considered it often. I’ve been developing for iOS for a few years now and I’ve become increasingly involved in the Objective-C open-source community via GitHub and CocoaPods, and was lucky enough to attend (my first!) WWDC this year on its 25th anniversary. It was an awesome experience. With that said, I can’t think of a better time or better reason to begin writing about my experiences with iOS and Objective-C (and now Swift), as well as my involvement in open-source. I hope to share worthwhile and interesting things here.

Continue…