How to Use iCloud While Only Kinda Using iCloud

iCloud
Apr 12th, 2021

Oh, iCloud.

We’ve got such a colorful, unique relationship. You are simultaneously one of the strongest aspects of the iOS ecosystem, while being a certain kind of frustrating from a developer experience. And no, I’m not talking about that ol’ chestnut…..or even the new one for that matter. I’m talking about how much power and opportunity you bring to the developer circle, but also the baggage of what it means to simply check the box for your entitlements:

But yet, learning you is a worthwhile endeavor. And today - we’ll quickly look at one your finest aspects. I’m talking, of course, about your user identifier. Allow me to apprise the uninitiated.

Querying a User Identifier

Absolutely nobody wants to sign up for another service, though it’s inevitable. Without question, it is my bête noire when it comes to modern software. That’s why, among other reasons such as privacy, I always opt for Sign in With Apple when it’s available. Quick, easy - I don’t have to mess with anything. You know what’s even better than using Sign in With Apple?

Sign in With Nothing™.

And that’s exactly what you can do with iCloud:

CKContainer.default().fetchUserRecordID { (userRecordID, error) in
    if let userID = userRecordID {
        print("We've got a user ID: \(userID.recordName)")
    } else {
        print("Mistakes were made: \(String(describing: error))")
    }
}

With that little snip, you now have a unique identifier tied to the user of your application. That will be linked to their active iCloud account, which at this point1 is as solid of a signal of a unique “user” of your software as anything else in the Apple ecosystem.

let concatenatedThoughts = """

Yes, the call is async. But we live in an async world at this point. Timing here really won't be an issue aside from, maybe, the first request you make to it. After that, getting the identifier takes less time.

"""

So - what’s the use case?

Let’s assume you’ve got a backend of some sort, or are sending your data over the wire from other means besides iCloud. Using this identifier, one can effectively match a user to that data - bypassing any need to sign in or sign up for another account. That grants your users with that “magic” feeling of picking up another device (say they’ve got your app on an iPhone and iPad) and having their data beam right down it, without having to do anything else.

Your syncing + iCloud’s user identifier can equal a whole mess of sign up dances being erased. We can also parlay Apple’s adherence to strong privacy to our advantage here too. There’s nothing you can know about this user other than a completely random identifier, as it should be for the majority of apps. You’ll also know if they signed into another iCloud account, because, well - the identifier will be different.

Caveats

Though, you do have to sign you binary’s soul away to Apple to get it. If you don’t add the entitlement for iCloud, you won’t get very far. LLDB will come knockin’, and fast:

libc++abi.dylib: terminating with uncaught exception of type CKException
*** Terminating app due to uncaught exception 'CKException', reason: 'The application is missing required entitlement com.apple.developer.icloud-services'

You can decide if the price of entry is worth it to you or not2, but for what iCloud brings - it’s hard to argue against it. I truly believe almost every app that handles sync benefits from the iCloud user experience more than anything. Plus, you can’t beat its price which is basically free all up and down.

Another obvious stopping point we’ve got here is Apple itself. This technique only proves useful to a small subset of developers, but it also means that your users would have to be exclusively on Apple devices. That may be the case for many of you solely making an app that won’t venture cross-platform waters, but many do. However, if you’re a SaaS person with only aspirations of being on Apple’s Ecosystem along with a web app, you could still kinda sorta do this by way of CloudKit JS.

Final Thoughts

Sometimes it’s the small things. If you need a quick solution to have some form of “identity” to your apps, iCloud could very well have you covered. Just know what you’re getting into when you activate its entitlements, because as far as I know - there’s no going back.

Until next time ✌️.

  1. Vendor lock-in with iCloud is so strong now, I don’t really know that anyone outside of a developer would routinely sign in and out of an iCloud account on their devices. 

  2. In case you skipped past the tweet at the lede, you can’t transfer apps if you use iCloud. Which stings if one of yours ever gets acquired. 

How to Be Okay When You're Not

The Indie Dev Diaries
Apr 8th, 2021

There’s a term, and I had never heard of this before, called “grief ambush”. It works like this: You’re just going about your day and things are normal. Then, out of nowhere - BAM! - you get this gut punch of emotions that takes your breath away. It happens while you’re navigating exceptional circumstances, and your thoughts idle away trying to make sense of your situation until their fight-or-flight mechanism kick in:

Grief Ambush

For the past four months, I’ve been dealing with some super odd medical issues - and I’ve run the grief ambush gamut. The timeline to even describe things at this point has become so mutated, shifted and varied that recounting things has become somewhat difficult:

  • I’m having trouble swallowing: ER visit
  • I can’t smell or taste anything: COVID
  • Now my chest hurts and I keep burping constantly (seriously): G.I Scope
  • But now I have shortness of breath and a fever: chest X-ray and labwork
  • Woah! Your liver enzymes are high: ultrasound
  • Your GI Scope shows a hiatel hernia and signs of eosinophilic esophagitis: perform biopsies
  • Now your liver enzymes are lower, but your white count is high and you have atypical lymphocytes and smudge cells: flow cytometry to look for leukemia or lymphoma
  • That’s clear, come back in six weeks: phew!
  • Six weeks later, you still have those things: check for cancer again
  • Ok, still no cancer, buuuuutt still wonky bloodwork: refer to hematologist

Needless to say, it’s been four months of at least 12 rounds of labs, tests and probably some other things I’m forgetting. I’ve shifted back and forth from “I think I’m okay” to “Wow this is still scary” more times than I can count.

But the big one? That big scary C word. When my bloodwork had shown signs of blood-based cancer - the time between hearing my doctor say as much and awaiting the test to either confirm or deny it were the longest six days I’ve ever lived so far.

And that’s where the grief ambush hit, two times in particular. The first time was a late Thursday night, after we got off the phone with my doctor. We went to a pharmacy to get some medications to help with my newfound anxiety. Lucky for us, a friend owns the pharmacy and they stayed late so we could get it. After we picked it up, I just got smoked by grief. I simply had to get out of the car and fast. As I opened the passenger side door, I quickly sunk down to the pavement crying my face off, “I don’t want to have cancer!”

In retrospect, I mean, who does?

The second time was when I went to the hospital to get my first flow cytometry test (via blood draw). At this point, I had become somewhat of a familiar face with the phlebotomists.

“Hey man, why are you back here?” one of the younger ones asked.

As they strapped on the tourniquet, I didn’t know how to answer non-awkwardly:

“They think I might have cancer”, was my reply.

And then another ambush! I started crying again as the needle stuck me, wondering out loud how this could be happening to me (“I’m young!”, “I’m healthy!”, etc). My sweet daughter crawled up on my lap and gave me a kiss, that was both terribly depressing and so lovely all at once.

That takes me to now, today. My story, thankfully, should end up being a happy one. One of those “cancer scare” stories. Others aren’t as fortunate. My hematologist believes this is a viral process my body just has to work through, and it simply takes time to level out. It’s as if COVID devised some sort of twisted machination, wherein my labs aren’t terrible but aren’t fine, stringing me along in hopes of a normal result the next time. So for now it’s labs once a month, and we’ll keep an eye on things. Could be worse.

So why am I telling you all of this?

Aside from the fact that I’ve not been one to shy away from personal topics, I learned a lot about myself while navigating things. Particularly, during those six days I awaited the results to see if I had cancer or not. And you know what?

I came away extremely proud of what I found. It literally dawned on me, this realization (shared below) is what let me be okay while I wasn’t.

Main Thing Is…

While wondering what was going to happen to me, I had to face reality that I might be battling cancer soon. And, once I did that, I had to also consider what could happen if I did. Namely, I could die. Sure, that’s going from step 1 to step 10,000 - but that’s what your mind does in these things.

If you were to find yourself in the same situation (or you’ve had the misfortune of doing so already), what would you think? I had the hallmark movie moment where I had to recount my life and the choices I’ve made up to this point.

I was relieved (and somewhat surprised) to conclude that I found no cause for regret, and given the chance - I’d run it all back the same way.

That’s a huge gift in a circumstance such as this, and it was the one thing that really helped ease my mind when things weren’t alright.

Imagine getting a terrible diagnosis, and then your very next thought is something like this:

  • I want to make my relationship with X or Y right, I wish I would’ve treated them better
  • I wish I would’ve spent more time with my kids
  • I wish I would’ve worked less when I didn’t have to
  • I wish I would’ve worked just a bit more to achieve that dream I had
  • …the list goes on

Can you imagine? That’s trauma stacking, and your mind can barely handle it all.

It begs the question in my own mind, and the long-winded point that I’m trying to make now that I’m on the other side - why and how did I approach things up to this point such that I felt at peace if it all ended tomorrow?

let concatenatedThoughts = """

Let's also be clear - I never bat 1.000 on these things. I've made a bevy of mistakes along the way, but that's not the point in this post. But rest assured, I'm no self-help guru. I just want to share a pivotal realization that brought me peace in an unpeaceful situation in hopes that it helps out anyone else.

"""

I’ve found that it’s two fold. The first reason I can think of is this; I’ve lived my life largely behind a mantra of “The main thing is to keep the main things, the main thing” and you’ll be ok. What are my main things? Straight from my Day One journal, they are:

  1. God/Christianity
  2. Family (my wife and kids)
  3. My health and fitness
  4. My career
  5. My indie work

Those are the things I value most in life, and in that order. Which is extremely important. Your list could look similar, maybe some things are switched around. Maybe it’s totally different - perhaps none of my things would be on your list.

Contextual Importance

The bottom line, though, is we all live by some sort of code. I’m glad I realized this before it might’ve been too late. Because a lot of those things, while important, can be put on hold. Some of them can’t. Knowing which ones are which saved me a lot of heartache.

So, secondly, from within that line of thinking - there falls two categories of things that I value:

  1. Things of true importance, and
  2. Things that are contextually important

Things that fall into category one for me are items 1-3. Those can’t sit and idle. They have to have attention and intention every single day I live, or my value system gets all out of whack and I no longer feel a mission or drive behind the things that I do.

Things that fall into category 2 are items 4 and 5. They are second, and while they are extremely important to me and they matter a great deal - when it comes to a hierarchy they can’t overtake items 1-3. Where I can get into trouble are times when I had them flip. Those were stressful times in my life where I might’ve got just one more line of code in instead of going outside with my kids, or skipping a date night to get some work in.

For me, it’s key to keep contextually important things just that. They can’t overcome your consistently important things. It also gives you the freedom to say things like “Yes, side projects are important to me, I enjoy them and value them” instead of merely responding to inquiries about them, like you have to include some sort of asterisk or explanation about why you value this that you love doing.

I don’t see any sense in that. Give yourself permission to pursue the things you love doing, and realize that order those things should be in. In my journal, I organized my goals around this idea, which I privately coined “top-down living”. Where the important goals are first, and then they ladder down to the next ones. That’s a post for another day.

But!

Since this is, of course, Swiftjective-C, this all ties back into indie life 😉. I really hope that you are enjoying some Xcode project you’ve been kicking around, or have been hammering away on that blog post you’ve been thinking about. Those are awesome things and you should enjoy them! Please, do!

But at the end of the day, if you get some crappy news, you won’t even think about them. You’ll think about the people you love, the impact you had or the legacy you’ll leave. For me, my indie endeavors, while important and completely deserving of some of my life’s mindshare, will remain in the background - where they should be in grand scheme of things.

This stuff, it’s wildly fun for me. But, not at the cost of things more important. I often get asked “How do you have a blog, apps, write a book or whatever else with a family and kids?” and the honest answer is - I don’t. I do all of those things outside of them, and only because I love doing it.

But as I’ve gotten older (and dare I say some permutation of wiser) I’ve realized that if my son taps my shoulder, or my wife wants to watch the same show on Netlix for the 1,000th time - I’m freakin’ there. My laptop stays tucked away, awaiting our next adventure in my backpack. And I’ve never once regretted that1.

Final Thoughts

One of the weirdest conclusions I’ve drawn from this experience is that to me, the thought of dying wasn’t scary. It was sad. I don’t want my wife to be alone with three kids. I don’t want my oldest to hang up playing ball because it would remind him of me, or my middle child losing his infectious laughter due to confusion. Or, my young daughter growing up with only a slight, vague memory of our time together.

But, if it did happen, I would be ready. I’d take my last breath on this ol’ rock filled with gratitude for the time that I’ve always given them. Or the dates I always took with my wife. And, absolutely - I’d be proud of the software I created, the words I’ve written or the impact (however small) that I’ve had.

But, I’d be proud of them in the right order - and that’s what counts.

Until next time ✌️.

  1. And honestly, like anything in life - it’s a tradeoff. Spend Stack took five years to ship because of this approach. But hey, all good when you consider the time I would’ve take from other things. 

Introducing The Daily iOS

The Indie Dev Diaries
Mar 12th, 2021

Today I’m happy to announce a little side project I’ve been kicking around for a few weeks:

Say hello to the The Daily iOS.

It tweets one code sample and one technical article daily from Apple’s documentation and comes complete with a link, generated image describing the code or article and alt text. The tweeted images look like this:

Code Sample from Apple's docs

The entire thing is all run daily from a Siri Shortcut automation on my phone.

Why

I’m asked fairly often how I discover new APIs or have learned certain techniques in the iOS ecosystem. There are several avenues I go down to teach myself new topics1, most of them fairly overt and obvious. Without question, though, among the most valuable ways to pick up new tricks are Apple’s own code samples and technical articles.

Say what you will about Apple’s documentation, there is no denying many of its most indispensable resources are tucked away on Apple’s developer website.

The issue is that Apple tends to bury the lede. Go to UIKit’s documentation and drill down four pages worth and you might stumble upon a code sample or article that could save you hours of heartache. From a hierarchical standpoint, the setup makes sense. From a discoverability angle, though, not so much. There’s not an easy avenue to surface these things. Ergo, The Daily iOS.

I built this tool while researching articles for my Best-in-Class iOS App book, but it also serves to further my goal of helping out Apple indie developers this year. I want this information front and center, and The Daily iOS will put it right where I’m at - Twitter 🤦🏻‍♂️🤷🏻‍♂️.

How

From the start, this project took me to technologies I had never used before. Web scraping, Kimurai, Ruby - it was a learning curve. That’s where the joy came from though, there’s nothing like googling how to do if statements or declare variables in a new programming language. It’s invigorating.

As I saw it, this is what I had to do:

Using Ruby…

  • Figure out a way to scrape Apple’s docs
  • Snag all code samples and articles listed
  • Separate it all by framework
  • Save it off locally as json
  • For each framework, separate empty results out

Then, with HTML + CSS…

  • Generate an image of the content
  • Allow for configuring the title, description, framework and type (Code versus Article)

Finally, using a Siri Shortcut…

  • Pick a random code sample and article
  • Parse its json
  • Generate the image mentioned above
  • Create the text for the tweet with a sanitized URL
  • Resize it for ideal Twitter media viewing
  • Upload the image somewhere to get a URL to it
  • Hit Buffer’s API to schedule the tweet
  • While doing this twice daily, fully automated

Done and dusted.

The scraping took the most time to figure out. Thanks to Mattt, I had a starting point. Parsing the .json proved infinitely easier than the raw HTML2 - but finding a suitable environment that allowed for debugging with Ruby was a challenge. There were many ways things could’ve became more complicated as well.

Take for instance, the image. I could use a service like Bannerbear and upload the result to AWS for a public link. Or, I could create a page on my site own that took in query string parameters to do the job, and then upload it to Imgur. That….that is much easier and it works.

I stand amazed at what’s actually possible when you push Siri Shortcuts. No cron job required here - my phone simply does it all (it’s on nearly nonstop anyways) and sends me a push notification of the result.

let concatenatedThoughts = """

While performing the work to scrape the information from Apple, I was surprised at what I didn't find as much as of what I did. Assuming my scraper had no errors, which is absolutely possible, 114 frameworks had no technical articles and 178 were without any code samples.

"""

As always, this work is open source and you can find the scraper, affectionately named Scrapple, here.

Final Thoughts

If a job is worth doing, then it’s worth doing well. What better way to improve your craft then to read directly from the people who make the tools? I hope the community gets some true value from The Daily iOS (I certainly learned several new things while creating it) and I look forward to it serving up some valuable information for years to come.

Until next time ✌️.

  1. I listed most of them here

  2. Thanks for the tip, Marco! 

Welcome to the bottom 👋.