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.
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.
shared
means that development of the client-side UI of a new feature is blocked until development of the endpoint is complete.shared
necessarily involves network access, use of shared
in unit tests can cause those unit tests to be slow or to fail altogether.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
.
This post introduces my new podcast, also called Race Condition.
This post presents learnings from seven years of completing take-home coding challenges for iOS-developer jobs. If you, the reader, intend to complete one of these challenges in the future, I intend to help you succeed. A model coding-challenge solution accompanies this post.
This post describes a multiple-pass strategy for ensuring the correctness and quality of pull requests.
Here are five proposed style guidelines for SwiftUI codebases.
This is a proposal for changing the spelling of the French word “crasher” to “cràcher”.
Communication is key. So key, in fact, that I recently imagined a new feature that could facilitate communication with users of my three apps, Conjugar, Immigration, and RaceRunner.
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.
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.
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.
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:
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.
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.
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.
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.
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.
In the 5.5 years that Immigration has been in the iOS App Store, several Android-device owners have asked me about an Android port. Immigration is my one side-project app that makes actual money, and I believe that the port represents a business opportunity.
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”.
This post consists of questions and answers about this website.
This blog post describes two techniques for getting more ratings and reviews.
This blog post describes, by way of a real-world example, how to use dependency injection to enable unit testing.
This post presents a concise method of initializing UIImage
s without force-unwrapping.
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.
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.
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.
This tutorial teaches programmatic layout (PL) by demonstrating conversion of an app’s user interface (UI) from Interface Builder (IB) to PL.