Space is Disorienting

Mobile Engineer

Read this first

Using Biometrics on iOS

I recently had to dig into biometrics on iOS and thought I would write some things down, mainly for the benefit of Future Me.

Process

Apple’s documentation has a good walkthrough of how to use biometrics to authenticate a user in your app. The process boils down to:

  1. Add NSFaceIDUsageDescription to your app’s Info.plist. This string is shown the first time your app attempts to use Face ID. If you don’t include it, your app will crash at this point.
  2. Create a LAContext object. See the note below about the expected lifetime of this object.
  3. Check what functionality is available on the device. You do this by calling canEvaluatePolicy(_:error:) on the LAContext and passing the desired LAPolicy.
  4. Once you have called canEvaluatePolicy(_:error:), biometryType is populated on the LAContext which indicates what biometrics are supported on the device. You can use this to update your UI (e.g. show...

Continue reading →


Refactoring Uber’s Rider app

There was a lot of discussion at the end of 2020 about Uber’s mobile apps, largely due to a Twitter thread by McLaren Stanley. Many wondered aloud why we didn’t just refactor the app instead of rewriting it.

I thought I’d add some context into where things were prior to the rewrite.

In the beginning…

Uber splash screen

I joined Uber in December of 2013, shortly after “Guinness” (a redesign of the app) launched. I was mobile engineer 8; I think all of engineering was around 130 people. At that time, the app had a fairly constrained feature set — "push a button, get a ride.“ Products like uberPOOL didn’t exist yet.

Trip Lifecycle

Trip states

When you dig into the lifecycle of a trip, there are several steps. The "core flow” breaks down into four main ones (shown above, albeit with a more updated design than existed at the time I joined):

  1. Looking — you’re effectively “browsing.” You haven’t set pickup...

Continue reading →


Using Elixir/Phoenix to poll BART arrival times

I started writing this post nearly 5 years ago, as I was starting to play around with Elixir and Phoenix. I’m publishing this to push me to finish writing the rest of the series.

I’ve recently been exploring Elixir and Phoenix. As an exercise I decided to write an app to poll BART train arrival times. I’ve done this in a couple of languages now, so it was interesting to see how Phoenix, Elixir, and the underlying Erlang VM simplified a number of pieces (e.g. API polling, websockets).

Note: This tutorial assumes a basic familiarity with Elixir and Phoenix and a working environment for the same. I’ll be using Elixir v1.12.2 and Phoenix v1.5.9. If you need help getting your environment set up, the Phoenix Installation Guide is a good place to start.

Part 1: Station Data

Create a new project

Let’s go ahead and create a new Phoenix project using the default Postgres database adapter and...

Continue reading →


macOS and the Responder Chain

I was working on an app in SwiftUI today, and one of the problems I ran into was how to add a button to toggle the sidebar. You can add SidebarCommands to your scene (via the .commands modifier) which will add a “Toggle Sidebar” item to the “View” menu, but there didn’t look to be a built-in way to add a button to do the same thing to the toolbar.

Creating the button and adding it to the toolbar is fairly straightforward:

content
    .toolbar {
        ToolbarItem(placement: .navigation) {
            Button(action: toggleSidebar) {
                Image(systemName: "sidebar.leading")
            }
        }
    }

The challenge comes in what to do in the callback (toggleSidebar) when the button is clicked. Many answers e.g. on Stack Overflow and the developer forums advocate for drilling down to the key window’s firstResponder and asking it to toggle the sidebar. This is certainly...

Continue reading →


Generating SQLite Databases at Build Time with Xcode

Background

Some years ago I worked on v2.0 of the Fly Delta app for Delta Air Lines. As an initial part of that effort, we mapped out the data model of what we would need in order to support all of the features that were planned. When it came time to start implementing, we instinctively reached for Core Data and ended up building out a moderately large Core Data model.

Unfortunately, we ran into several issues with Core Data. I have forgotten most of the details now, but I believe they had to do with threading/merging changes from multiple managed object contexts and bulk deleting data (e.g. if you deleted your user account from the app we would need to purge all of your trip information). Ultimately, we decided that Core Data was more trouble than it was worth and ended up switching to SQLite.

Note: This may not be the best fit in every situation, and Core Data has come a long way...

Continue reading →


Versioning and Xcode

If you’ve ever used agvtool to manage versioning your project you know it’s a pain. Among other complaints, I’d rather not have version information buried in project files (or have to modify that project file to bump the version).

Pre-process Info.plist

My initial reaction was to extract the version into something like an xcconfig file and use plist pre-processing to inject it into the Info.plist. The issue there is that Xcode doesn’t correctly pick up changes to the xcconfig file (it’s presumably looking at mod times of the Info.plist file itself), so any version bumps require a clean build to pick up.

Build Rule

My next thought was to use a build rule to process the Info.plist file manually. The downside there is that you need to change the INFOPLIST_FILE build setting to point to the processed file in the derived sources directory, but doing so disables Xcode’s built-in editing...

Continue reading →


Deciphering Xcode’s index

At work we’re having to wait an inordinate amount of time for Xcode to finish indexing our rather large Swift project. I’ve consequently spent a lot of time over the past few weeks digging into the internals of indexing. This is more or less a brain dump of what I’ve discovered thus far.

File structure

Xcode’s index is broken into a number of files, located in {project derived data}/Index/{build config}/{platform}/{project}.xcindex/:

db.xcindexdb
db.xcindexdb-shm
db.xcindexdb-wal
db.xcindexdb.strings-cmp
db.xcindexdb.strings-dir
db.xcindexdb.strings-file
db.xcindexdb.strings-moduleurl
db.xcindexdb.strings-res
db.xcindexdb.strings-sym

SQLite files

  • db.xcindexdb: The index’s SQLite database, which we’ll cover below
  • db.xcindexdb-shm: The SQLite shared-memory file
  • db.xcindexdb-wal: The SQLite write-ahead log

Strings files

These files are collections of strings separated by 0x00...

Continue reading →


Singular Resources in Phoenix

I recently stumbled across Elixir and Phoenix. The more I dig in, the more I’m drinking the Kool-Aid and loving it. Coming from Rails, things feel familiar, but there has definitely been some grinding of gears as I’ve ramped up.

One of the things I ran into today was how to make a “singular resource” for something like a user profile or account. My first instinct was to do something like this:

 web/router.ex
scope "/", MyApp do
    ...
    resource "/account", UserController
end

That didn’t work. It complained about not finding the function resource/2:

== Compilation error on file web/router.ex ==
** (CompileError) web/router.ex:31: undefined function resource/2
    (phoenix) expanding macro: Phoenix.Router.scope/3
    web/router.ex:17: MyApp.Router (module)
    (elixir) lib/kernel/parallel_compiler.ex:116: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

At this point...

Continue reading →


When Full-Disk Encryption Goes Wrong

Last September I watched in horror as my MacBook Pro slowly died.

It started with a text from my wife:

iMessage.png

“Hmmm,” I thought. “Maybe the System folder or something got corrupted. Should be a quick fix.” Little did I know that we had just lost every piece of data on that computer.

Side note: I love that the only thing the MacBook is displaying is an icon equivalent of ¯_(ツ)_/¯. No helpful error message, nothing. Just a “Yeah, I’m not even going to try.”

I’ve been a “computer person” for most of my life. I worked in tech support in high school and college, so I went through a pretty exhaustive list of things to attempt to get the computer to boot.

After a few unsuccessful attempts at getting the system to boot off the disk (and the usual exorcism of zapping the NVRAM a few times for good measure), I booted into Apple Hardware Test.

Continue reading →


The Apple Watch: Impressions After 1 Year

I stayed up late the night of April 9, 2015 to pre-order the Apple Watch. I actually ordered two — work was paying for them, and we wanted to ensure there were enough devices for the team (we were busy putting the finishing touches on our watch app at the time). The device I kept was a 38mm Apple Watch Sport.

The Good

Comfortable

I’m not huge into watches. I used to occasionally wear one for a few hours on the weekends. I’ve been fighting pain in my wrists for years, so the thought of wearing a watch all the time was a pretty tough sell. Sure enough, when the Apple Watch finally arrived and I put it on it was pretty uncomfortable.

After a few days of this I swapped out the band for the larger one and moved the watch to my non-dominant hand. Both of these improved the comfort immensely. Props to the team at Apple — you can not only swap which wrist you wear it on but also flip the...

Continue reading →