Yesterday I joined my friends Dan Moren, Mikah Sargent, and Guy English on Clockwise.

On this episode, we discussed how we manage charging, how we manage windows, how we manage weather, and how we manage travel.

Clockwise is such a change from my normal podcasts, because it’s so darned fast. Which makes it the fun kind of stressful. :)


 

It appears that this blog is turning into a Ted Lasso linked list and, well, I’m not sure I find that to be a problem. ⚽

Here we are, nearly at the end of the three-season run. As I write this, only one more episode left. 😢

This week I joined host Chip Sudderth and fellow guest Aleen Simms to discuss this week’s episode, Mom City. Chatting about Ted Lasso episodes is fun, even if the episodes aren’t my favorite. Mom City was a little spotty to start, but hoo boy did it get good.

There’s only one more episode of Ted Lasso left. I’ll be sad to see it go, but I’m already excited to listen to the Football is Life recap.


 

I’m a sucker for a guest invite to a podcast. Particularly one about Ted Lasso.

This week I joined internet pals David J. Loehr and Sarah Hendrica Bickerton to discuss this week’s episode of Ted Lasso. I felt like this one was a particularly good one, and all three of us were firing on all cylinders. There was a lot to talk about, as this season of Lasso has been… up-and-down. But we’re nearing the end, so all the varied checks that have been written will need to be cashed soon.

A good sign the episode was fun is when the source material is shorter than the recap podcast reviewing it. 😇 Whoopsie doopsie. At least we’re not that bad, right? 😆


 

Football is life!

Ted Lasso is back, and I swung back by the virtual offices of The Incomparable to record another episode of Football is Life, their recap podcast. On this episode, I joined host Kelly Guimont and co-panelist David J. Loehr as we discussed the episode.

This episode of the show was a long one — nearly double the length of a typical Ted Lasso episode — and as such left us a lot of room to discuss. There’s also a ton of interesting choices made by nearly every character. Naturally, this was a blast to record, especially with such wonderful co-hosts.


 

Ted Lasso is back, baby!

Last week I joined my pals Moisés Chiullán and Jean MacDonald to have a chat about the second episode in season three of Ted Lasso, (I Don’t Want to Go to) Chelsea.

On this episode of Football is Life, we had a lot of discussion about how one can see traces of Star Trek in this episode, how Roy Kent is wonderful, who really is the boss of KJPR, and more.

It’s always lovely to talk to Moisés and Jean, and doubly so when we get to discuss one of my favorite TV shows.


A Decade of ATP

The beginnings were… odd.

“What is it that makes somebody buy a white car?”
“Oh, you’re a 🍆.”

Perhaps it’s fitting — given my predilection for… coarse language… that this was my podcasting debut. Me calling Marco a… ahem… “jerk”.

Neutral began in January, but by March, we knew that the car show had mostly run its course. However, what began as an after-show on Neutral had come into its own.

Ten years ago today, we formally launched the Accidental Tech Podcast. A show borne out of our idle chatter after our “real” podcast.

Ten. Years. Ago. Today.

A full decade.

When we launched ATP, I was working as a .NET developer at a local consulting firm. John was just a few years into a job he would, years later, end up leaving to go independent. Marco hadn’t yet announced Overcast.

I had no children. Marco’s son wasn’t even a year old. John’s youngest was barely out of preschool.

Now, I have two children; the youngest of which enters Kindergarten next year. Marco’s son is soon to be in middle school. John’s youngest is not too far from college; his eldest is already there.

A lot of time has passed. All during the Accidental Tech Podcast.


The start of ATP is somewhat nebulous — was it when Marco released us goofing off on Soundcloud? Perhaps, but for me, I always felt this was the start of ATP:

Ten years ago today.


I am indescribably lucky to be able to talk to my friends — including Myke as well — and earn money for doing so. I take the work very seriously — and sometimes it really is work. But more often than not, even if it’s work, it’s also tremendous fun.

It’s thanks to our listeners, and probably you, reading these words, that we are able to sell ads and memberships and make a living doing something we love.

Thank you, so very much, for making these last ten years possible. Here’s hoping the end is nowhere in sight… 🤞🏻


 

I’ve listened to Upgrade since episode one. It’s one of my favorite tech podcasts, and honestly, one of my favorite podcasts, period. Myke and Jason do a phenomenal job of regularly re-inventing the show, keeping it extremely fresh even after nine years.

This week, I filled in for Jason while he was on a well-deserved vacation. Since Myke and I regularly record Analog(ue) together, I was curious what kind of rhythm we’d fall into for the episode. I’m really pleased how it turned out, and I think Myke and I both did a pretty good job.

On the episode, we discussed Apple’s “moonshot” team, new iPhones, the Mac Pro (yes, really.), and played a new game together. Myke also asked me a bunch of listener questions, which was extremely fun.

I like to think it was a good one.

Another good one you should check out is the episode prior, when my dear friend Dave filled in for Jason. That one was unquestionably excellent.


 

This week I joined my pals Bryan Guffey, Dan Moren, and Mikah Sargent on Clockwise.

On today’s episode, we discussed how modern-day internet search is both impressive and disappointing, what we’re doing with AI tools, the ethics behind AI voice generation, and our favorite Black technologists.

We ran nearly an hour on this recording, which left quite a challenging edit for poor Dan this week, as Clockwise is 30 minutes or less. 😬


It’s been said that the whole of iOS development is turning JSON into UITableViews. There’s probably more truth to that than I care to admit.

Often times, especially when working on an app as part of a company’s in-house team, an iOS developer can work with the server/API team to come to an agreement what JSON will be used. Sometimes, especially when working as an independent developer, the API is “foreign”, and thus the JSON it emits is outside of an iOS developer’s control.

Occasionally, APIs will make choices for their JSON structures that make perfect sense in more loosely-typed languages, but for strongly-typed languages like Swift, these choices can be more challenging. The prime example of this is JSON’s heterogeneous arrays.

In JSON, it is completely valid to have an array of objects that are not alike. An extremely simple example could be [1, "two", 3.0]. In more typical examples, these arrays won’t hold primitives but rather objects, and each object in these heterogeneous arrays will typically have vastly different key/value pairs. It’s easy to store heterogeneous arrays in Swift as an array of Dictionaries, but that… isn’t very Swifty.

What’s the more Swifty version, then? Preferably using Decodable?

This post is my attempt to describe exactly that.

Let’s assume you’re hitting some web API that describes a restaurant. It will return a restaurant’s name, as well as its menu, which is a heterogeneous array of objects that represent drinks, appetizers, and entrees.

Let’s further assume that the developers of this API made some annoying choices about how to name things, such that there’s no clear and easy way to make a base protocol that all the menu items can inherit from. 😑

So, some example JSON may look like this:

{
    "name": "Casey's Corner",
    "menu": [
        {
            "itemType": "drink",
            "drinkName": "Dry Vodka Martini"
        },
        {
            "itemType": "drink",
            "drinkName": "Jack-and-Diet"
        },
        {
            "itemType": "appetizer",
            "appName": "Nachos"
        },
        {
            "itemType": "entree",
            "entreeName": "Steak",
            "temperature": "Medium Rare"
        },
        {
            "itemType": "entree",
            "entreeName": "Caesar Salad"
        },
        {
            "itemType": "entree",
            "entreeName": "Grilled Salmon"
        }
    ]
}

The restaurant, Casey's Corner, serves two drinks, a Dry Vodka Martini and a Jack-and-Diet. It serves one appetizer, Nachos. It serves three entrees, Steak (which has an associated temperature), Caesar Salad, and Grilled Salmon.

The type of each menu item is defined as part of the menu item itself, using the itemType key. Note that we don’t particularly care about this key in our Swift objects, as their type will implicitly give us this information. We don’t want to clutter our plain old Swift objects with an itemType property.

How can we represent this in Swift? Most of this is straightforward:

struct Drink: Decodable {
    let drinkName: String
}

struct Appetizer: Decodable {
    let appName: String
}

struct Entree: Decodable {
    let entreeName: String
    let temperature: String?
}

struct Restaurant: Decodable {
    let name: String
    let menu: [Any]
}

Note that the menu property is Array<Any>. Again, in most examples, you’d probably be able to avoid this, and figure out some sort of common base type instead. I wanted to have a clear, bare-bones example that shows how to do this all by hand, no base types allowed.

For Drink, Appetizer, and Entree, we can rely on the automatically synthesized Decodable implementations: no further work required.

Restaurant is a whole different story, however.

The thing is, we need to be able to peek into the menu JSON array in order to see itemType for each menu item, but then we need to back up and actually decode each menu item. This gets wonky fast.

Here’s how I did it:

struct Restaurant: Decodable {
    let name: String
    let menu: [Any]
    
    // The normal, expected CodingKey definition for this type
    enum RestaurantKeys: CodingKey {
        case name
        case menu
    }
    
    // The key we use to decode each menu item's type
    enum MenuItemTypeKey: CodingKey {
        case itemType
    }
    
    // The enumeration that actually matches menu item types;
    // note this is **not** a CodingKey
    enum MenuItemType: String, Decodable {
        case drink
        case appetizer
        case entree
    }
    
    init(from decoder: Decoder) throws {
        // Get the decoder for the top-level object
        let container = try decoder.container(keyedBy: RestaurantKeys.self)
        
        // Decode the easy stuff: the restaurant's name
        self.name = try container.decode(String.self, forKey: .name)
        
        // Create a place to store our menu
        var inProgressMenu: [Any] = []
        // Get a copy of the array for the purposes of reading the type
        var arrayForType = try container.nestedUnkeyedContainer(forKey: .menu)
        // Make a copy of this for reading the actual menu items.
        var array = arrayForType
        
        // Start reading the menu array
        while !arrayForType.isAtEnd {
            // Get the object that represents this menu item
            let menuItem = try arrayForType.nestedContainer(keyedBy: MenuItemTypeKey.self)
            // Get the type from this menu item
            let type = try menuItem.decode(MenuItemType.self, forKey: .itemType)
            
            // Based on the type, create the appropriate menu item
            
            // Note we're switching to using `array` rather than `arrayForType`
            // because we need our place in the JSON to be back before we started
            // reading this menu item.
            switch type {
            case .drink:
                let drink = try array.decode(Drink.self)
                inProgressMenu.append(drink)
            case .appetizer:
                let appetizer = try array.decode(Appetizer.self)
                inProgressMenu.append(appetizer)
            case .entree:
                let entree = try array.decode(Entree.self)
                inProgressMenu.append(entree)
            }
        }
        
        // Set our menu
        self.menu = inProgressMenu
    }
}

The trick here is just before, and within, the while loop. Like we realized above, we need to be able to peek into each object in the menu array. However, in doing so, we advance the position of the arrayForType container, which means we can’t back up and grab the whole object for parsing into a Swift object.

Thus, we make a copy of arrayForType container, called array, which we use to decode full objects. When the arrayForType container advances, while we decode itemType, array does not advance. This way, when we try to decode() our Drink, Appetizer, or Entree, arrayForType has moved on, but array has not.

I’ve put all this in a gist on GitHub. I’m sure that other Swift developers will have thoughts on my approach here; if you’re that person, please feel free to either leave a comment on the gist, or fork it.


Some [Happy] ATP Housekeeping

ATP has had some fun things going on lately, and I wanted to call attention to them.

First, and in my perspective most importantly, I’ve been podcasting with my dear friends Marco and John for a decade‼️ The first episode of Neutral debuted on Thursday, 17 January, 2013. I’m incredibly thankful that this little adventure I started on has changed from a goof, to a side hustle, to a profession.

A decade. My word.


In mid-2020, ATP launched a membership program. At the time, we offered an ad-free feed, and a small discount on our time-limited merchandise sales. A little while later, we added “bootlegs” — raw releases of our recordings moments after we hit “stop”.

The membership program has been going well, and I’m extremely thankful to anyone who has joined. 💙

Late last year, we decided to do some one-off, members-only episodes. We really wanted to do right by all our listeners, so these episodes are additive — they don’t involve any of the usual ATP subject matter, and if you skip them, it shouldn’t in any way hurt your enjoyment of the normal show.

To start off, we started “ATP Movie Club” by each of us choosing a movie for the other two hosts to watch:

When deliberating what to choose for my movie, I decided to choose something that neither John nor Marco had seen. Both John and Marco expected me to choose The Hunt for Red October, but I really wanted a movie neither of them had seen; John had seen Hunt before.

This week, we righted that wrong went back and covered The Hunt for Red October. While the whole discussion was tremendous fun, we immediately got derailed arguing about the best way to make popcorn. As it tends to be, when the three of us get into it with each other, that makes for some of the most fun listening.

None of the above should be a surprise to regular ATP listeners, but I wanted to call attention to it here on my website, too.


We’ll probably do some ATP Movie Club episodes again in the future, but as I write this, we plan to put that aside for at least a little while. We have a tentative plan for something new for our next members-only episode, but we’ll see what shakes out, and when it happens. No promises.

If you have an idea of something fun for the three of us to do, please feel free to reach out to all of us or just to me. We’d love some ideas or inspiration for things to do in the future!

And if you’re not already a member, I’d love for you to check it out.