By Casey Liss
 

Generally speaking, I don’t care for doing podcasts with video. Often, I don’t feel like video adds too much. Worse, for audio-only listeners, video allows me to make reference to things that only those watching can understand. More than anything else, though, my home office is usually a wreck, and embarrassing to have on camera. 🙃

A month or two back, David Lewis asked me to join him for an episode of his podcast, and do so on video. Initially, I told him “No video! No way!”. However, in a fortuitious turn of events, I had just cleaned my office for Relay FM’s Feuding Families, so I told David “let’s do it”.

Available both as a podcast, and on YouTube, David and I spoke about my history as both a developer and podcaster. We discussed what it’s like to build an app from idea to launch, how and why some apps are successful and some aren’t, and more.

As David said to me privately when we were done recording, whenever you do an interview with someone — irrespective of what side of the table you’re on — it’s always a bit of an unknown. Perhaps you’ll get along great with the other person, or perhaps it’ll be like pulling teeth. Chatting with David was, for me anyway, really fun. I think you’ll hear (or see!) that in the conversation. 😊


 

Most podcasters joke that there are two primary rules of podcasting:

  • Don’t discuss politics
  • Don’t discuss parenting

Today, I broke the second rule, and spent 90 minutes talking parenting with my friend Max Roberts on his Max Frequency Podcast.

Max is just a few short weeks away from becoming a dad for the first time, and naturally, had some questions. Though my advice is probably surely garbage, it was fun to be compelled to relive the time when Declan was brand-new.

On the episode, we couldn’t help but discuss Apple’s new announcements a little bit. However, this episode is predominantly me trying to do the impossible: help someone about to have their first child understand what they’re in for. Hopefully my advice was more useful and actionable than “sleep now, while you still can”.


When one is “in the trenches” parenting, it can occasionally be difficult to remember why you’re here. To remember all the work you put in to have a child. This conversation with Max was a really great reminder that even though kids can drive you nuts, they’re an incredible gift. No matter how challenging they can be, every single child is a miracle.

Some of my friends just sent their first-born off to college; others are soon-to-be empty-nesters. To relive the infant stage with Max was a fun way to remind myself that not only can it be worse 😆, but that every stage is a gift.

 

Accessibility, on the surface, seems like it’s affordances for people that don’t have " normal " bodies. That’s a very immature and ignorant view, and one that’s patently wrong. It’s also the opinion I’m ashamed to admit I held as a younger man. As with many things, it took a clarifying, first-hand, experience to help me realize how wrong I was. It only takes one experience trying to read things on your phone with your eyes dilated to realize accessibility is for everyone. If not today, then tomorrow.

With that in mind, I was really excited when my pal Shelly Brisbin asked me to join her and Robin Christopherson on her accessibility-focused podcast, Parallel. On the epidose, we discussed this month’s Apple announcements, with a bent toward accessibility. Speaking with someone who is low-vision, and someone who is blind, is absolutely fascinating. In this one-hour conversation, I learned a ton about how those with true vision challenges navigate not only their world, but their devices, too.


Converting a Verizon Wireless SIM → eSIM

Yesterday, Apple announced the iPhone 14 and iPhone 14 Pro. While they added a lot, like satellite connectivity for emergencies, a much improved camera sensor on the 14 Pro, and crash detection.

However, they also took away. From the iPhone 14 Pro specs page:

iPhone 14 Pro and iPhone 14 Pro Max are not compatible with physical SIM cards.

Hm.

My iPhone 13 Pro currently has a physical SIM in it, and though I’d assume Apple would have a plan for upgrades like this, you never really know. This is also complicated because I buy phones unlocked; I wonder if the upgrade path is a little squishier when you’re not replacing an existing device with one locked to your same carrier.

So, in order to hopefully get ahead of the game for next week, I decided to try to convert my physical SIM to an eSIM. As it turns out, this process wasn’t particularly difficult, but I figured it’d be worth documenting for others.

The instructions below will only be useful for my carrier, Verizon Wireless.


First, make sure you’re on both the cellular and Wi-Fi networks, as there is a chance you’ll need to fall back to Wi-Fi at some point during the process.

Next, log into your account. I did all of this on my Mac; I can’t speak for how it’d work on either mobile web or the app.

Once you’re logged in, find your phone, and click Manage device.

On your device page, scroll down and find this section:

Activate or Switch Device

Click Activate a SIM.

At this point, Verizon knew that I had a 13 Pro, and offered for me to use one of the onboard eSIMs:

Use my iPhone 13 Pro's eSIM

Naturally, I clicked Use my IPHONE 13 PRO's eSIM [sic].

At this point, I was punted to an instructions page, which I didn’t really need to bother with. The rest of the process happened on the phone. I didn’t think to take screenshots of this, unfortunately.

On my phone:

  1. Open Settings
  2. Right at the top, I noticed a line that said something like Finish Setting up Cellular, which I tapped.
  3. At that point I basically followed a wizard that completed the setup

A couple things worth noting:

It took a few minutes for the activation to complete, on a random Thursday morning, before everyone in the world is trying to upgrade their iPhones. I’d estimate maybe 3 minutes?

🚨 BE CAREFUL 🚨

After I did my transfer, I noticed that iMessages were suddenly being sent and received as text messages. This may have been user error on my part, but it seems that my iMessage settings were altered such that my phone number was no longer a valid iMessage address for me.

If you do the above, it’s probably worth verifying your settings. To do so:

  1. Open Settings.
  2. Scroll down and tap Messages.
  3. Tap Send & Receive.
  4. Verify your phone number is checked. In my case, my email address was checked, but my phone number was not.
  5. If it isn’t checked, tap your phone number to check it.

It’ll take a minute or so, and then iMessages should start coming back in.


After posting, Leon Cowle reached out via Twitter to provide instructions that seem to have worked for him on AT&T.


Travel Setup, 2022 Edition

Just yesterday, Mikaela received her second shot of the Moderna vaccine, and as such, the Liss family is, for now, as protected as we can possibly be against COVID-19. As such, it’s time to start thinking about travel again.

I’ve preached the gospel of the “Go Pack” before — in 2018, 2015, and 2014. However, in today’s world, there’s a lot more to traveling than just charging your devices. For a nerd like me, there’s a software component as well.

Now is a great time to revisit not only my Go Pack, but also the software I use to power my travels, and the “everyday carry” pieces that I keep in my laptop bag.

Note that for some of these links, I’ll get a small kickback if you end up purchasing the item using the link. However, I’m linking to this stuff because it is legitimately the stuff I use and carry.

Laptop Bag

Seven years on, I’m still using a Tom Bihn Cadet. The laptop that gets stuffed in there has changed probably five times, but the bag has not. Further, it still looks brand-new. Everything I said in my review of the Cadet, from seven years ago (!), still stands.

I keep a handful of items in my laptop bag, particulary when traveling:

Some items I keep in my laptop bag
  • AApple MagSafe Battery Pack — $100
    As with all things Apple, this is absurdly priced, but it is so convenient to be able to just slap it on the back of a dying iPhone and go about your day. Plus, since it’s MagSafe, it should work with future phones for years to come.
  • BRavPower 90W GaN Wall Charger — $55
    I bought this on Amazon before RavPower was evicted. Regardless, this is a two-port USB-C charger that supports up to 90W. I can power my 14" MacBook Pro, as well as my iPad, or other USB-C devices, no sweat. There is nothing unique about the RavPower charger; any GaN charger with 2+ ports would be fine.
  • CZMI PowerPack 20K — $50
    A portable battery pack that can charge my computer, iPad, or phone. What’s unique about this one is that it can also operate as a USB hub, so if I’m off working at a park, I can plug both my phone and computer into the battery, and then put the battery in hub mode. That way, the PowerPak is directly powering both the phone and the computer, and I can tether without needing Wi-Fi. The battery comes with a pouch, a short USB-A → [Micro-USB or USB-C] cable, as well as a short USB-C ↔ C cable.

Go Pack

The Go Pack is a package of cables, chargers, dongles, and other doodads that is used only when traveling. I never take something out of the Go Pack for use around the house; instead, I buy a duplicate of that item. The sanctity of the Go Pack cannot be infringed.

The pack itself is still a Harry’s Toiletry Bag, which costs $20. I’ve been using this bag as my pack for years, and you can barely tell. That said, any bag would do, and if I weren’t using this one, I’d start by scouring the Tom Bihn website.

Inside, the Go Pack recently got considerably simpler:

Some HDMI cables and some chargers
  • D — 2× Slim HDMI cables — $12 each
    Pictured here are two different slim HDMI cables, as well as a HDMI coupler. The particulars on these cables and coupler don’t really matter. However, whenever I’m in a hotel or AirBnb, I tend to plug in either my iPad, computer, Switch, or some combination thereof. As such, it’s nice to have at least one — and often two — HDMI cables available. The coupler is in case I want to extend an existing cable, rather than adding my own.

  • E — 2× mophie 3-in-1 travel charger with MagSafe — $150 each
    Okay, so, hear me out. These things are incredibly expensive, but they dramatically simplified my Go Pack. Previously I needed a multi-port USB charger, some USB extension cables, lightning cables, Apple Watch chargers, etc. These stupidly expensive travel mats made all of that go away. With space for a phone, AirPods, and an Apple Watch, these things are magical. I am cheap frugal as they come, but this was worth the price.

    Apple claims they’re only available at Apple, but I’ve been told that they can also be found at Zagg, sometimes at a discount, especially if you are willing to briefly sign up for their newsletter. Your mileage may vary.

    I will also say that once or twice I’ve noticed my phone wouldn’t charge when placed on the charger; if that happens, it seems disconnecting the charger from the wall and plugging it back in solves the issue. Technology. 🙄 Still, these things simplify my setup so much that disconnecting them once daily and the absurd price are worth it to me.

    As a final note, they do come with very nice carrying cases. However, I prefer to have everything freeballing it in the Go Pack, as the two chargers, cords, and wall warts take up far less space that way.

A television remote control, and some dongles.
  • FInteset 4-in-1 Universal Learning Remote — $26
    I stole this idea from my pal Merlin Mann. It’s often been said that TV remotes are cespools of filth and germs, and given how gross people are, I believe it. Recently, I started carrying this remote in the Go Pack, which you can reasonably quickly and easily get to work with nearly any TV. I keep a copy of the instruction manual in Apple Notes; in it are the codes you use to program the remote.

    However, since most hotels and AirBnbs tend to buy from only two or three TV manufacturers, I’ve often found that a setup I programmed for an entirely different location will work at a new place.

  • GGE Grounded 3-Outlet Tap — $8 for 3
    Often times, the wall outlet around a TV is completely full, but I wish to plug my laptop or iPad in there. This small “tap” allows me to easily add a couple more outlets, without having to bring a full-on surge suppressor.

    Note that the ones I have don’t seem to be available anymore, but I’ve linked the equivalents above.

  • HTP-Link USB-C to Ethernet Adapter — $20
    Though I find I almost never have the opportunity to use Ethernet anymore, I still like to carry an Ethernet adapter with me, just in case. This one is super-slim, and supports gigabit. I also often carry a slim Ethernet cable with me, though I did not picture one.

  • IApple Lightning to Digital AV Adapter — $50
    Also filed in the extremely-rare-but-would-hate-to-need-it-and-not-have-it department, the annoyingly expensive Lightning → HDMI adapter. It’s very, very rare that I wish to play my phone to a TV, but you can’t do it without this adapter.

  • JApple USB-C Digital AV Multiport Adapter — $70
    Thanks to my new MacBook Pro, I don’t need this stupid dongle nearly as much as I used to. However, I do semi-often want to plug my iPad Pro into a TV, so, I have to come crawling back to this annoyingly expensive dongle.

Software

Most normal humans can skip this entire section. This is for the nerds.

For me, I like to have access to my at-home network and devices no matter where I am. Generally speaking, to do so, that means a VPN, which in turn means that my traffic is encrypted. Having an extra layer of encryption around my internet traffic makes me feel far better about using foreign Wi-Fi, like at a coffee shop, or grocery store café, and so on.

In my personal opinion, there are two solid options for running your own VPN.

Tailscale

Tailscale is a new-ish entry that is like a VPN, except it isn’t… usually. As the saying goes, it’s complicated.

The advantage to Tailscale is that it’s very easy to set up, mostly works like magic, and is mostly bulletproof. There are some caveats though.

First of all, any device you want to be able to access via Tailscale needs to have the Tailscale client installed… usually. This is not particularly hard nor egregious, but it means more software to be maintained in more places. Furthermore, instead of using your devices’ native IP address — say, 192.168.1.17 — instead, you use a Tailscale-assigned IP (or hostname), such as 100.113.1.2.

What makes Tailscale great is that you can access 100.113.1.2 always, irrespective if you’re at home or not.

Tailscale runs on top of the we’ll-get-to-it-just-hold-on WireGuard protocol. However, you should not think of it as a traditional VPN. Rather, you should think of it as a way to connect to your devices remotely. Out of the box, Tailscale does not encrypt all traffic. It only does so between your devices. So, if you go access anything on the internet, Tailscale is not involved. Tailscale only steps in when you try to access your own devices.

Except.

Tailscale nodes can optionally elect to offer to run as an “exit node”. Other nodes can then optionally elect to use one of those exit nodes. If a client device — say, your laptop — elects to use an exit node, then Tailscale operates more as a traditional VPN, where all traffic is encrypted, and runs through that node.

However.

Even despite routing all your traffic, you still can’t access other devices on your in-home network without also setting up a “subnet router” as well. The subnet router will let you access devices on your network that aren’t running Tailscale.

If you have the wherewithal to remember to engage the exit node functionality as needed, Tailscale is pretty great. Depending on your needs, it may be fiddly, but it’s great nevertheless. Furthermore, their free plan is pretty generous.

For me, however, I want something a bit more seamLiss.

WireGuard

WireGuard is an open-source VPN that you can run on nearly any device. What’s great about WireGuard is that you can optionally set up the WireGuard client to automatically connect whenver you’re not on your home Wi-Fi. This works on macOS, iOS, and iPadOS.

It’s this auto-connection magic that makes me prefer WireGuard over Tailscale. There’s a feature request on Tailscale’s Github to add this functionality, but it seems to have fallen on deaf ears.

WireGuard can be a nightmare to set up, but I used the extremely-easy PiVPN script to set it up on a Raspberry Pi 4 that I use for this and for pi-hole. Using PiVPN made setup a breeze, and it even gives you a QR code you can scan with your devices to add the VPN into the WireGuard client software.

Thanks to WireGuard, whenever I connect to Wi-Fi that isn’t my home network, WireGuard automatically connects, and sends all of my traffic through my home. This gives me access to my in-home devices, and helps me feel protected from prying “eyes”. As an added bonus, I get a [mostly] ad-free browsing experience, since I now have access to my pi-hole as well.


 

This week, I had the pleasure of joining my pals Dan Moren, Mikah Sargent, and fellow guest Heather Kelly on this week’s Clockwise. Always a blast, and always 30 minutes or less, Clockwise is a whirlwind, and a ton of fun.

For this episode, we discussed our favorite iPhones, how we protect our privacy online, sleep tracking, and where we enjoy working outside the house. For members, we also discussed our notetaking workflow.

I enjoy Clockwise immensely, even if it is a bit stressful — everything moves so fast! If you haven’t given it a try, you absolutely should.


In November, I purchased a brand-new MacBook Pro, complete with Apple’s fancy new M1 Max processor. This is, without reservation, the best computer I’ve ever owned. It is faster than my beloved iMac Pro, but considerably more portable.

At the time, I was working on what would eventually become MaskerAid. Very quickly upon getting to work on my new computer, I realized that things weren’t working properly on this new machine. After some research, it appeared that some aspects of the Vision Framework were not available on Apple Silicon based Macs.

Apple’s mechanism for providing them feedback is the aptly-named Feedback Assistant (née Radar). It is a full-blown app on macOS/iOS/iPadOS. In fact, if you happen to be on an Apple device, try this link. Radar was a black hole, where issues went to die get marked as duplicates. Feedback Assistant, despite trying to pull the “Xfinity trick”, seems to be the same as it ever was.

Regardless, I filed a Radar Feedback — Apple people, if you happen to read this, it’s FB9738098. When I filed it, back in 3 November 2021, I even included a super-simple sample project to demonstrate the issue.


Apple’s feedback system is fundamentally broken — at least, for everyone who does not work at Apple.

In the roughly 225 days since I filed that feedback, I received precisely zero… well… feedback. Apple is a big company, and surely gets an unimaginable amount of feedback filed every single day. However, I have zero indication that a human has looked at my bug. To me, it went into the black hole, never to return again.

Thankfully, by virtue of my day job, I’ve had the occasion to make the acquaintance of quite a few Apple engineers. I reached out to someone who, let’s just say, should have insight into how to fix my problem. They were very helpful, and very apologetic, but their response was, in my words, “tough shit”.

Sigh.


Fast forward to early this month, and it’s WWDC. One of the best not-so-secret secrets about WWDC is that the labs are where it’s at. You can, from the comfort of your own home, spend ~30 minutes with an Apple engineer that is likely to be intimately familiar with the APIs you’re working with. So, I signed up for a lab to beg for someone to fix my bug.

I didn’t expect much to come of this lab, and I started by telling the engineer I spoke with that I expected it to take just a couple minutes. As I told them, I was just there to beg for them to fix my bug.

The engineer’s response?

“Well, I do think this is only going to be a couple minutes, but it’s better than you think: I have an easy workaround for you!”

🎉


In short, when you make a request of the Vision Framework on an Apple Silicon Mac, it fails every time.

Sample code
/// Asynchronously detects the faces within an image.
/// - Parameter image: Image to detect faces within
/// - Returns: Array of rects that contains faces.
///
/// - Note: The rects that are returned are percentages
///         relative to the source image. For example:
///         `(0.6651394367218018,`
///          `0.527057409286499,`
///          `0.0977390706539154,`
///          `0.1303187608718872)`
static func detectFaces(in image: UIImage) async throws -> [CGRect] {
    typealias RectanglesContinuation = CheckedContinuation<[CGRect], Error>
    
    return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in
        guard let cgImage = image.cgImage else {
            print("WARNING: Couldn't get CGImage")
            continuation.resume(throwing: FaceDetectionErrors.couldNotGetCgImageError)
            return
        }
                    
        var retVal: [CGRect] = []
        let request = VNDetectFaceRectanglesRequest { request, error in
            if let error = error {
                print("WARNING: Got an error: \(error)")
//                    continuation.resume(throwing: error)
                return
            }
            
            if let results = request.results as? [VNFaceObservation] {
                retVal.append(contentsOf: results.map(\.boundingBox))
            } else {
                print("WARNING: Results unavailable.")
            }
            
            continuation.resume(returning: retVal)
        }
        
        let handler = VNImageRequestHandler(cgImage: cgImage,
                                            orientation: CGImagePropertyOrientation(image.imageOrientation),
                                            options: [:])
        

        do {
            try handler.perform([request])
        } catch {
            print("ERROR: Request failed: \(error)")
            continuation.resume(throwing: error)
        }
    }
}

The error you receive is as follows:

Request failed: Error Domain=com.apple.vis Code=9 "Could not create inference context" UserInfo={NSLocalizedDescription=Could not create inference context}

Back in my lab, I asked the engineer what they were talking about. As it turns out, I simply needed to add one line, against my instance of VNDetectFaceRectanglesRequest:

request.usesCPUOnly = true

That’s it.

Apparently it will force the Vision Framework to use the CPU and not GPU for its computations. Pretty crummy for a real device, but no problem when you’re just trying things in the Simulator.

Having my problem worked around, in the span of five minutes, with a single-line code change is both delightful and incredibly frustrating.


I got to thinking about this lab again this morning, and I’m pretty upset by it. Ultimately, I got what I wanted, but why couldn’t I have had that OVER TWO HUNDRED DAYS AGO‽ It’s infuriating.

Furthermore, as a parting shot, the engineer asked me if I ever bothered trying to talk to someone by using one of my Tech Support Incidents. The engineer meant it in good faith — they were trying to say that I didn’t have to wait from November → June to get an answer. But in a way, I almost find this more frustrating still.

Why is this the accepted way to get the attention of an engineer? For something as simple as a one-line code change, why are my only two options:

  • Wait for June and hope I get an audience with the right engineer at a lab
  • Use one of my two Technical Support Incidents and hope it’s fruitful… and that I don’t need that one for something else later in the year

Were my problem put on the desk of the right engineer, who was incentivized to provide useful and actionable feedback, it could have been worked around in just a few minutes. I just needed a reply to my feedback with the one-liner.

Unfortunately, Feedback Assistant and Radar are tools for Apple, and they serve Apple’s needs and only Apple’s. They are a complete waste of time for outside developers. I maintain that they are a black hole into which I pour time, effort, sample code, and [often useless] sysdiagnoses. I get nothing in return.

Apple swears up and down that Feedbacks are useful. I’ve been told many times, by many teams, that they also use Feedbacks as a de facto voting mechanism to try to get a pulse on what external developers want. I’ll leave it as an exercise for the reader to think about how utterly broken that is.

Instead, let me make it clear what developers want:

Let’s start there, if you please.


 

Over the weekend, I appeared on John Gruber’s seminal podcast, The Talk Show. On the episode, we kick things off by deliberating the right way to make a martini. Afterwards, we spend some time discussing the complete lack of decent Apple monitors on the market for the last half-decade. Finally, we round out the chat talking a bit about the genesis of, and reception to, MaskerAid.

I had a ton of fun on this one, and it meant a lot to me.


MaskerAid Follow-Up

Yesterday I launched my new app, MaskerAid. It’s too early to tell how the response has been in terms of numbers. In terms of sentiment, however, the response has been great!

If you were still holding out on trying MaskerAid — which is free to try! — you may wish to check out what these fine folks had to say about it:

MaskerAid also seems to have found itself a ton of use cases, other than simply hiding your own children’s faces. Some of these I never expected, and all of them are very clever:

  • Teachers may find that they wish to share shots within their classroom, but don’t necessarily need to fuss with determining which students have social media releases filed.
  • Foster Parents aren’t legally allowed to post photos of the children they’re fostering. Despite, I would imagine, them often (always?) feeling like they’re members of the family.
  • One may find that the profile photo they want to use for dating apps happens to be a group shot. By putting emoji on the other faces, it’s clear who is the one looking for love.
  • Protestors are, sometimes without hyperbole, taking their lives in their hands by standing up for what is right. MaskerAid can be a useful tool to keep their identities private.
  • The same is true of soldiers.
    🇺🇦 I stand with the people of Ukraine. 🇺🇦
  • On a more fun note, MaskerAid is an excellent way to obscure faces in amusement parks, or even better, on rides themselves.
  • If a boudoir photographer wanted to share a photo that’s perhaps just a bit too risqué, MaskerAid can be used to tastefully (or humorously!) cover that which should not be shown.

If you haven’t given it a whirl yet, I’d love for you to give MaskerAid a try.


 

Today, I’m overjoyed to announce my latest app, MaskerAid!

My kids, with emoji in front of their faces.

In short, MaskerAid allows you to quickly and easily add emoji to images. Plus, thanks to the magic of ✨ machine learning ✨, MaskerAid will automatically place emoji over any faces it detects. There’s several reasons you may want to hide a face:

  • The face of a child who is too young to consent to their image being shared
  • The faces of the children in your classroom, or your own classmates, who really don’t need to be in your images
  • The faces of protestors who are standing up against a grotesque war
  • The other faces in a particularly great shot of you, but was taken as part of a group

There are other reasons you may want to simply add an emoji to an image, but not on top of a face:

  • Perhaps you want to point ⬆️👆⬇️👇⬅️➡️👈👉 to something
  • Let’s just say 🍑 + 💨 = 😆
  • Who doesn’t love a ✌️ behind a head?

MaskerAid is free to try but you may only add 🙂 to images. There is a one-time $3 in-app purchase to unlock the rest of the emoji.

MaskerAid app icon

MaskerAid is designed to be a very particular kind of app: do one thing, do it well, and do it quickly.

For me, I really really wanted an app that would let me quickly hide the faces of my children, so I could post family pictures to the internet, but keep their faces private. In much the same way Peek‑a‑View was written to scratch my own itch, so was MaskerAid.

Animated GIF of MaskerAid in use

MaskerAid is free to try, and I’d be honored if you would. If you like it, buy the in-app purchase, and more than anything else, tell your friends!

The Back Story

When my oldest child, Declan, was a baby, we posted pictures of him frequently. Not only were we new parents, but we were first-time parents, and we had just finished a nasty journey. I like to think we earned it.

However, when Declan got to be around four, it occurred to me — much to my dismay — that he was no longer a little squish. He was an honest-to-goodness person, with a personality, desires, and opinions. Which got me to thinking: what if he doesn’t want me posting pictures of him to my social media? Today, he certainly doesn’t care, but what about tomorrow? What about when he’s in high school?

I mostly stopped posting pictures of him, excepting on his birthday. When I did post, I would generally hide his face using an emoji, as such:

This isn’t awful to do on Instagram, but it’s not exactly easy. The best way I had found to do it was to make an Instagram Story, save it, and then use that as your image for your post. It’s a pain.

What I wanted was an app that would let me do a couple things:

  1. Add an arbitrary emoji to an image
  2. Place emoji over the faces within an image automatically
MaskerAid's drawer allowing you to choose an emoji

I figured I could conquer #1, but #2 seemed harder. I know very little about machine learning, but I know enough to know that training a model to recognize faces would be exceedingly difficult.

Then I had an apostrophe epiphany.

Apple has already done the work for me.

I started to make a proof-of-concept using UIKit. I just wanted to be able to put rectangles around the faces detected in a photo. I quickly hit several walls, most of which were probably my fault, but it seemed silly to spin my wheels. So I gave the same task a quick college try in SwiftUI, and it took no time.

I was off to the races. Within the first day, I had the bare-bones proof of concept complete.

But Wait, There’s More

As with all my other apps, I did a private beta test for a handful of trusted friends and some press. Even though the beta only went to about forty people, those testers gave me immensely useful feedback. Myke, in particular, pointed out to me something I should have seen but didn’t. MaskerAid is excellent for adding an emoji anywhere, to any image. Even images without faces can often find themselves in need of an emoji; perhaps for fun, perhaps to hide something that isn’t a face.

Once Myke called this to my attention, I noticed other testers doing the same thing. Suddenly I realized I have a whole new class of user to consider. Ultimately, this new use-case didn’t dramatically change any of my plans for MaskerAid, but it is a testament to:

  1. Always show your work to trusted advisors
  2. You never know how people will want to use your software

Myke also made a second great suggestion. Instead of marketing around a [sort-of] negative of hiding things, why not lean into the fact that MaskerAid can be used to add emoji anywhere? Annoyingly, #mykewasright.

The Work

Two lovebirds

Unfortunately, a bare-bones app is not appropriate for sale in the App Store. It took me from late September until late February to get MaskerAid to the point that I felt like it was ready to be released. I’m sure others would work faster, but there’s a surprising amount of work that goes into making a modern iOS app these days.

Though MaskerAid probably doesn’t look like it took nearly half a year, I assure you I was not just mucking about during that time. Further, this isn’t my first rodeo: not only have I been working on iOS professionally since 2016, this is my fourth app that I’ve released independently.

It’s surprising to me how much time I spent working on what is kinda “administrivia” — things like the in-app purchase flow, making sure the handful of user preferences I keep are saved properly, and updating emoji without having to update the app. (We can all learn from Slack’s mistakes, amirite?)

I don’t say this to complain — by and large the app has been tremendous fun to work on — but more to point out that even “simple” apps have quite a lot going on under the hood.

Other Factoids

For the nerds, here are some tidbids you may find interesting. MaskerAid:

  • Uses async/await semi-liberally
  • Uses Combine occasionally.
  • Is almost exclusively SwiftUI
  • Is exclusively Swift
  • Leverages Gui Rambo’s excellent tip about storing app information in iCloud; this is how I can update emoji without updating the app
  • The first commit was 21 September, 2021
  • The last commit for version 2022.2 — the one released today — was the 203rd, and was made Friday morning.
  • There are 29 closed pull requests (from me to me 🤪)
  • As of writing, there are 64 closed GitHub issues, and 12 open ones.

Some Acknowledgements

Though I wrote every line of code in MaskerAid, I definitely had some help along the way that I haven’t mentioned yet:

  • Ste Grainer provided yet another wonderful icon for me — I’ve relied on Ste for both the Vignette and Peek‑a‑View icons before. However, more critically, MaskerAid was Ste’s idea and I knew immediately that it was the right name for the app.

  • Spencer Wohlers provided many, many useful and actionable bug reports during beta testing.

  • Mark Jeshcke provided nearly as many bug reports, but even more critically, lent his far superior design eye to the app. Thanks to Mark’s ideas and tips, MaskerAid was shaped into something quite a bit more attractive than I could or would have made alone.

  • More than anyone else, my family, for inspiring the app, being patient with me while I worked on it, and just generally being more awesome than I can ever hope to be. 🥰

It’s scary to put something new into the world, but I’m so happy to be able to let MaskerAid out into your hands. I really hope you’ll try it.