A Blog by Josh Adams



Blog


Introducing iOSExpert

Don't just crack the iOS interview. Crush it!

Loyal readers of this blog may have noticed a decrease in post frequency since January 2023. The reason for this decrease is that I spent most of 2023 creating a video course, iOSExpert. This post describes iOSExpert and presents some learnings from the creation process.

Continue…

Cracking the iOS-Developer Coding Challenge, SwiftUI Edition

Don't just crack it. Crush it!

In a recent post, I presented an approach for succeeding on take-home iOS-developer coding challenges. (For brevity, I henceforth refer to these particular coding challenges as “coding challenges”.) The model solution in that post used UIKit because, at the time I wrote the post, I had already completed coding challenges using that framework. But SwiftUI may be a good, or indeed the best, option.

My goal in this post is to help readers who are are considering or have been assigned a SwiftUI-based coding challenge.

This post presents factors for the UIKit-or-SwiftUI decision. This post then addresses certain challenges posed by a SwiftUI solution, including architecture, dependency injection, testing, image caching, and Identifiable.

In the course of discussing these considerations and challenges, this post introduces a SwiftUI model solution, KatFancy, and uses that solution for illustrative purposes.

To derive maximum benefit from this post, readers should review the original post before reading this one. Most of the content of that post is relevant to all coding challenges.

Continue…

Dependency Injection of URLs and URLSessions

Much Benefit

URLSession “and related classes provide an API for downloading data from … endpoints indicated by URLs.” Most iOS developers are familiar with using the URLSession singleton, shared, which has “reasonable default behavior”, including retrieving data from the actual endpoint represented by the URL specified.

But using shared in all circumstances has some drawbacks.

  1. In a production app, during development of a new feature, the endpoint may not exist until late in the development cycle. Using shared means that development of the client-side UI of a new feature is blocked until development of the endpoint is complete.
  2. Because using shared necessarily involves network access, use of shared in unit tests can cause those unit tests to be slow or to fail altogether.
  3. The endpoint may not return the data needed to exercise all functionality of the app. For example, the app may have a special no-data-was-retrieved state, but if the actual endpoint has data, this state can’t be triggered.

This post presents a solution to these three problems: using a stubbed version of URLSession and using alternate URL variants, both via dependency injection.

Paul Hudson described the URLSession-stubbing technique in this excellent article. My post contains two refinements to his article, both described in the section Acknowledgement.

Continue…

Improving Long and Long-Running Terminal Commands

Four Weird Tricks

I recently contributed to SwiftSyntax, a subproject of the Swift open-source project. Building Swift and its subprojects from scratch and then unit-testing them takes about three hours, and the Terminal command is both long and complicated. A build-and-test run can output more than a megabyte to Terminal. Some of this output is potentially useful for diagnosing build-or-test failures. As an iOS developer, I haven’t spent much time in Terminal, but, in the course of running long and long-running Terminal commands recently, I reacquainted myself with some Unix tricks that I developed in the late 90s while working primarily on AIX, which, like macOS, is a Unix. These tricks could potentially benefit anyone running Terminal commands that are long, that take a long time to complete, or that generate a lot of output.

Continue…

Two Applications of Life Experiences

Troubleshooting & Persuasion

I took an extended break from the software industry. For one of those years, I was an IT guy. For eight of those years, I was a lawyer. I haven’t hitherto mentioned this period on my blog, one mercenary goal of which is to enhance my iOS-developer brand. But I value the skills I acquired during these years because they remain useful. This post describes two examples.

Continue…

Software Development as Creative Expression

The Importance of Norms and Style

Science is about revealing objective truth, for example the orbit of Earth around the Sun or the ultimate interchangeability of matter and energy. Kurt Krebsbach has argued that “computer science”, despite having the word “science” in its name, is not a science. If Krebsbach is right, what is software development, which I define, for the purposes of this post, as the practical application of computer science? I view software development as a form of creative expression, often fun, that sometimes has the side-effect of creating a useful artifact, a piece of software. This post posits that norms and style are important in software development, as in English-prose composition, another form of creative expression.

Continue…

SwiftUI

Now, Overview Available

I recently modified one of my apps, Conjugar, to use SwiftUI rather than UIKit for its settings screen. I hereby present, for the reader’s edification and enjoyment, some observations and learnings from this process. I cover:

  • Spurious reasons not to learn SwiftUI
  • How to learn
  • Naming
  • Dependency injection in a mixed UIKit/SwiftUI app
  • Stack Overflow filling a gap
  • Animation
  • Unit-testing SwiftUI

Continue…

Trailing Closures

Not Considered Harmful

A significant portion of my workday consists of browsing and grokking code that other people have written. I have had the experience of being frustrated, upon encountering a trailing closure, not knowing the name or therefore purpose of the argument being passed. This frustration initially caused me to consider forswearing trailing closures in my side projects. But with the benefit of contemplation and research, I have concluded that trailing closures are sometimes useful. This post describes how I reached this conclusion, recounts the history of trailing closures, and describes an analog from Kotlin.

Continue…

Hobby Apps

What Kind to Make?

In the past couple of years, I have spoken to several aspiring iOS developers about what kind of hobby app they should make after escaping the tutorial trap. By “hobby app”, I mean an app for which one does not intend to be paid at all by an employer or enough by users to cover one’s living expenses. As someone who used hobby apps to jump-start his iOS-development career and who continues to develop hobby apps, I am interested in this question. I share my thinking in this post with the hope of providing thought-food to anyone considering development of a hobby app.

Continue…

Dependency Injection in Practice

Preparation and Techniques

Dependency injection makes unit testing possible and development easier. This post describes the process of preparing an app for dependency injection, as well as implementing three approaches to dependency injection: constructor injection, Swinject, and The World.

Continue…

Non-Optional, Constant Properties

One Advantage of Programatic Layout over Interface Builder

In a tutorial I created last year, I described advantages of programmatic layout (PL) over Interface Builder (IB). I recently became aware of another: PL permits use of non-optional, constant properties of view controllers. IB does not. I share this advantage here for the benefit of readers.

Continue…

Migrating This Website to HTTPS

How I Learned to Stop Worrying and Embrace the Secure-Socket Layer

I recently converted racecondition.software to HTTPS. This post discusses this change and will act as a smoke test, by which I mean that if this post doesn’t show up in my RSS reader, I will have more work to do.

Continue…

Changing Immigration's Business Model to Subscriptions

Motivation and Benefits

I recently changed the business model of my iOS app Immigration from paid-up-front to free-with-subscription. This post describes the reasons for and results of this change. The target audience for my blog has heretofore been, and will always remain, iOS-app developers, but, in a break with tradition, the target audience for this post is people affected by this change, in particular the app’s users. Because they are mainly lawyers, I hereby give myself permission to use legalese like “heretofore”.

Continue…

Implementing SiriKit in RaceRunner

How I Stopped Worrying and Learned to Love an Intent Domain

My run-tracking app, RaceRunner, has features focused on racing and training for races. One of these features is alternate methods of ending runs. Here is an example.

The typical way to stop a run in a run-tracking app is to tap a button. RaceRunner supports this. But because of the physical exertion involved in running a race, a runner is sometimes in no condition to unlock an iPhone and tap a button at the end of a race. Even unlocking can be tricky because sweat often prevents TouchID from working, so instead the passcode must be tapped. So RaceRunner supports two alternative ways of ending a run. First, a run can stop automatically after a certain distance. This is great for time trials or if the runner does not trust the race organizers’ distance measurement. (A time trial involves running a certain distance, typically a race distance, as fast as possible.) Second, a spectator can use RaceRunner to stop the runner’s run. Both of these alternate means of stopping have problems. The certain-distance method may result in a recorded time that differs from actual time. The spectator method requires a cooperative spectator with an iPhone. So I implemented a third method: Siri.

Having just released a new version of RaceRunner with Siri support, I thought I’d share some learnings and pedagogic resources for other developers interested in implementing Siri support.

Continue…

Free and Low-Cost App Assets

Some Learnings from Five Years of Side-Project Development

I make iOS apps as a means of supporting my family and as a creative outlet. On the creative side, I have released three apps in the past five years: Immigration, RaceRunner, and Conjugar. Like many side-project apps, mine have had small budgets for asset creation. But they have greatly benefitted from free and low-cost assets (FALCAs). In this post, I introduce five sources for these FALCAs: Coolors, icon websites, Google Images, Sound Jay, Incompetech, and Free App Store Preview Music.

Continue…

How My Code Has Improved in Three Years

Some Learnings from RaceRunner

RaceRunner is a run-tracking app I wrote in Swift three years ago. This app got my foot back in the door as a professional software developer, and I continue to use it. Since RaceRunner’s release, I have periodically updated the code to support new versions of iOS.

I’ve heard some software developers say that they can’t bear to look at code they wrote a long time ago. There are aspects of RaceRunner that would not pass my own code review today. But rather than being embarrassed by or ashamed of how I wrote RaceRunner, I find that a review my old code illustrates my improvement as a software developer. This improvement elicits both pride in how far I have come in three years and excitement at how far I might go in the next.

The purpose of this blog post is to examine this improvement through the lens of one part of one source file in RaceRunner.

Continue…