I followed these 7 simple steps and became an iOS coding test BOSS!
So you took the bait. Your route to success starts here! đ¤ But unlike the many get-rich quick schemes promised on the side-panes of particular websites, I hope to actually deliver on my click-bait.
When completing an iOS coding test, there are a number of simple ways to make your submission stand out and give reviewers confidence that you know what youâre doing.
The common theme here is:
If you want someone else to love your code, then you need to love it yourself.
By following the suggestions below, interviewers will barely need to look at what your code actually does. Good programming techniques can be taught after youâve landed the job. Itâs more difficult to teach someone to love their code. But itâs so important! After all, you shouldnât need to be taught this, given this is your chosen career. đ¤
I donât want this article to come across as arrogant; Iâm not suggesting going through a companyâs hiring process is easy. I just want to help people that are completing coding tests to make their submission the best it can be. I think there are a few very simple ways to do that.
It shouldnât take a long time to make a simple app as part of a coding testâdepending on experience of courseâbut you donât want it to appear rushed. Show your code the love it deserves. Itâs easy to keep your code clean and it all starts with the app delegate.
UIApplicationDelegate
Usually known as the AppDelegate
, this is the entry point into your app. As such itâs the first place interviewers look. If your code was a book, this would be the first page. Show it the love it deserves and an interviewer will love it too.
For a simple test, your AppDelegate
could look as simple as this:
The window
property is required if youâre loading your interface from a storyboard. You donât have to load your interface from a storyboard, but for a short coding test itâs the simplest thing to do. Itâs the default when creating a new Xcode project and you probably wonât be required to create too many screens in a simple test. There are advantages to loading from a .xib
, but the pros and cons are something you should feel confident talking about at interview stage rather than demonstrating in your test submission.
Even the application(_:didFinishLaunchingWithOptions:)
method is not necessary. (Itâs an optional method in the UIApplicationDelegate
protocol.)
The AppDelegate.swift
file thatâs created by default with a new project comes with a load of commented-out method implementations that donât do anything. Get rid of them. This rule should be applied across the whole of your projectâs codebaseâŚ
Get rid of empty methods
By empty methods, I mean methods that only call the super classâ implementation and/or only contain comments. These are usually methods that were created for you by Xcode when you created a file from a template. If you donât need these methods then delete them.
This is what a UIViewController
subclass will look like when you create it:
The first thing you should do when creating this file is delete the template code. Youâll know if and when you need to implement viewDidLoad
and youâll know to call the super
implementation (well, you should know). Donât clutter your codebase with comments unless you think they will benefit the prospective employer reviewing your code. They probably already know that the viewDidLoad
method is where you âdo any additional setup after loading the view.â So remove the comment and remove the method if you donât need it. (And of course, remove the comment block that includes the prepare(for:sender:)
method.)
Before submitting a test, go through the codebase with a fine-tooth comb for any code that you wrote as part of âwork in progressâ that may no longer be needed. If code is no longer needed, donât just comment it out, delete it. Itâs also best not to leave comments to explain what youâre doing. Code should be self-documenting, so if you find yourself leaving a comment, instead try to find another way of writing the code to make it more clear whatâs happening. Often this is as simple as moving the code into separate method.
Another place to look for redundant code is in your unit test target. If you selected to create unit tests during project initialisation, thatâs great, but please donât just submit the auto-generated template methods. Itâs such a tease for the reviewer that wants to see tests. If you donât need the setUp
and tearDown
methods, delete them. Reviewers donât want to see the below submitted as part of a coding test.
Make it simple
Itâs not always easy to make something simple. Making something simple is a challenge and when doing so, youâre doing it for the benefit of the consumer:
- Make a user interface thatâs simple to navigate by a user.
- Make an API thatâs simple to consume by another developer.
- Make a presentation thatâs simple to understand by your audience.
- Make a test project thatâs simple to review by someone thatâs probably reviewing a lot of tests.
The last point there is much simpler than the others. Making a simple user experience is a challenge. Making a test project simple to review should be simple itself. You donât need to demonstrate your knowledge of every architecture pattern under the sun.
You can talk about your love of MVVIP-UPVCA at interview stage. đ
A reviewer shouldnât mark you down for fulfilling their requirements in the simplest way possible and often this means using the MVC pattern promoted in most Apple documentation. Donât worry, you can still demonstrate your in-depth knowledge of the SOLID principles! You can show you understand the advantages of dependency injection and youâll have more time to do so if youâve used a simple architecture. You might even save enough time to implement the odd unit test. Iâve seen too many test submissions with some mutant variation of the VIPER architecture, but without a single unit test or even an app icon.
Being pragmatic is important in programming. You need to determine when an elaborate architecture is appropriate. For an app of two or three simple screens, itâs probably overkill. Donât just keep it simple, make it simple.
Itâll be better use of your time to group related files into Xcode groups (and therefore directories on disk). This is another great way to show the reviewer how you keep yourself organised and it makes reviewing your project a breeze. But again, donât go overboard. If every .swift
file is in its own group then youâve misunderstood the definition of grouping. There are lots of different ways to group and thereâs no right or wrong, within reason. For a simple project, I suggest grouping your model objects together; grouping any networking/backend-related components; grouping user interface components by feature/screen. Go with what youâre comfortable with and make sure you have a rationale for how youâve organised your files.
Removing empty methods also contributes to making your app simple to review and the methods you have should be kept as small as possible. To âkeep methods small and files smallerâ is an impossible challenge, but I dare you to try.
Thereâs no need for three or more levels of indentation. Instead call out to another method. Because methods are named, they make your intention much more clear than yet another level of indentation. If youâre calling out to another method in the same file, you should declare that method private
âŚ
Understand access control and mutability
Demonstrating that you understand access control and mutability can go a long way with reviewers. Donât give them anything to find fault in.
This is Swift best practice 101:
- Make everything
private
first, only exposing when necessary - Make everything
let
first, only usevar
declarations when necessary - Make your class types
final
if youâre not subclassing them
If youâre unsure on any of the above, go with the most restrictive first (private
, let
, final
) and increase flexibility only if really needed.
For example, if youâre not sure what should be private, then make everything private, hit Build and see what fails to compile so you know what must be exposed. Any code that isnât private
should just be left with no access modifier at all; no need to declare anything internal
as itâs the default and itâs unlikely youâd need to declare anything public
in a coding test. But anything that can be private should be.
Any views or subviews (such as those declared with the@IBOutlet
decorator) should definitely be private. Incidentally, @IBOutlet
properties are the only excuse for implicitly unwrapped optionals or any type of forced unwrapping/casting. Iâm referring to the dreaded exclamation markâŚ
Avoid forcing! anything
âUnconditional unwrappingâ (or forced unwrapping) is where you incorrectly assume an optional wonât be nil
at runtime. A common example is retrieving the first or last element in a collection, e.g. let heroImage = images.first!
. Always assume the worst. Even if youâve set the images up from a static list, you cannot guarantee it wonât crash at runtime. Always assume the worst! It shows that you understand the use of optionals and you understand that just because it doesnât crash now, that doesnât mean it wonât crash if someone changes the code later. Use if let
or guard let
syntax to ensure you have the non-optional you require.
Forced type casting is where you incorrectly assume one type can be treated as another type at runtime. A common example is when reading from a [String: Any]
type dictionary. Youâll read values like so:
let name = dictionary["name"] as! String
let age = dictionary["age"] as! Int
Using as!
is dangerous. Even if youâre confident it wonât crash at runtime, you donât have the guarantee of Swiftâs strong type system. So always assume the worst and safely unwrap these using as?
like so:
guard let name = dictionary["name"] as? String,
let age = dictionary["age"] as? Int else {
return
}
Implicitly unwrapped optionals are those declared with a !
next to their type when originally defined. A common example is a view model that you will provide later, so you know itâs gonna be there, right? Right?! Wrong! Implicitly unwrapped optionals are a lazy hack to get your code to compile, e.g. var viewModel: ProfileViewModel!
. The exclamation mark on the end tells the compiler youâll give this a value later and it can assume it wonât be nil
, so the compiler wonât require you to do the if let
/guard let
dance. But itâs dangerous. You can avoid this either by declaring your property as a normal optional with ?
after the type, or by ensuring the property is passed in on init
, so you donât have to use an optional at all. The latter is preferred because it means you can declare the property with let
and you donât need the if let
syntax because youâve explicitly defined that it cannot be nil
.
@IBOutlet
properties are a commonly accepted exception to the above. I once saw a project where even these were declared optional, but I think thatâs overkill. The way I see it is this will definitely come out in testing and youâll have bigger problems on your hands if your view doesnât exist. At any rate, you certainly wonât be marked down in a coding test for declaring your@IBOutlet
properties as implicitly unwrapped optionals. Just make sure theyâreprivate
. Subviews are an implementation detail and should not be exposed to the outside world. If you want to allow another object to modify state of a subview, such as setting text on a label, then create a setter method or property (usingset
/get
). This makes your intention explicit and means that the outside world cannot accidentally corrupt your view, e.g. changing a labelâs background colour.
Meet the requirements
If you donât follow any of my previous suggestions, you should at least follow this one. My previous suggestions are code-related and following them will make your submission stand out.
This suggestion will ensure the reviewer actually looks at the code youâve slaved over and doesnât just reject it immediately.
The first thing I do when reviewing a test submission is to run the app in the simulator, so you should ensure your project:
- builds on the latest version of Xcode
- builds and runs out-of-the-box, without the reviewer having to install dependencies (other than Xcode of course)
- looks as you expect on all supported screen sizes and devices
- looks as you expect when the device is rotated, unless youâve explicitly disabled rotation
Then make sure your project meets the requirements laid out in the test description. Check each of the requirements and double check that youâve covered them.
If you donât understand any of the requirements given to you by a prospective employer, you should check with your contact at the company. Donât make them feel bad for not explaining the criteria clearly enough, after all you want them to give you a job, so be nice. Politely ask for clarification and feel free to go back and forth as much as necessary until you fully understand whatâs required of you. This demonstrates a collaborative way of working.
If you cannot meet the requirements, donât worry too much, presumably itâs due to a lack of experience and thatâs fine! Thereâs always something to learn, so donât worry! Explain the difficulties and explain what you tried. Write it up in the README.md file or in an accompanying email. If you notice bugs that you donât know how to fix, let the reviewer know and hopefully theyâll work with you at interview stage to find a solution together.
If you donât explain, then the reviewer will have no choice but to assume you either missed the requirement(s) completely or chose to ignore them. Both of which are equally as bad.
Once youâre happy youâve met the requirements and your codebase is as clean and tidy as it can be, then youâre ready to submit, right? ButâŚ
Donât submit a test, submit an app!
Youâre applying for a developer role and you want to make apps, right? So make an app! An app has an app icon. Sometimes even a catchy title. Show that you take pride in your work.
There are plenty of free tools online to convert an image into all the necessary sizes for iOS app, such as https://makeappicon.com.
You wouldnât upload an app to the App Store with no icon, so why treat a job application any differently?
The same applies to the app name. Perhaps this isnât so important, but why not surprise the reviewer with a creative app name. Donât include the word Test
in your app name. You wouldnât submit to the App Store with this name and it can get confusing with test targets which by default append the Tests
suffix (e.g. RecipeCodingTestTests
). If youâre asked to make a recipe app, show your creativity with the app name (unless the requirements state otherwise)⌠Recipeasy
, Recipe Idol
, Recipe For Me
, Bake With XYZ
where XYZ is the company name to which youâre applying. These are all better names than RecipeCodingTest
.
Pretend youâre wrapping up your project ready for the App Store, but also for others to collaborate on in future. Of course this wonât be the case with your coding test, but in reality itâs very unlikely youâll be working alone once you start the job. Adding a README.md file isnât always required, but itâs so easy, so why not? You only need the project name and brief description. But for the purpose of the hiring process, you could use the readme to describe any challenges you faced or anything youâd do in the future, i.e. a project roadmap or TODO list. If you write a TODO list, ensure it lists future features that youâve thought of yourself, features that are out of scope of what was asked of you. Donât submit an incomplete test or explain that you ran out of time. And remember the readme is for project collaborators (i.e. the reviewer). The readme is not an App Store description for your users.
While youâre applying the polish, itâs as good a time as any to check that any images in your app are not stretched. Set any image viewâs content mode to âAspect Fillâ in Interface Builder or set it to .scaleAspectFill
in code.
To summariseâŚ
- Keep the app delegate tidy, itâs the entry point to your project.
- Remove empty methods and methods that only call the superclass implementation; remove any commented work-in-progress code.
- Make it simple to review; keep the architecture simple and keep the workspace organised.
- Demonstrate your understanding of the importance of access control and mutability; if in doubt, go with
private
/let
/final
. - Avoid forced unwrapping, forced type casting and implicitly unwrapped optionals.
- Meet the demands of your prospective employer; show that you can follow instructions; donât be afraid to ask them for help and be honest about what you donât knowâeveryone has room for improvement!
- Wrap it up and tie it in a bow; give it an app icon and a name that shows your personality and creative spirit.
Next steps
I believe the above suggestions can followed by anyone, regardless of experience. But there are of course lots of things you can do over and above this to demonstrate more experience if you have it, such as demonstrating an understanding of Git, unit testing, UI testing, Fastlane, SwiftLint and âhotâ language features such as Codable
.
Whether you are actively applying for jobs or youâre recruiting and reviewing tests yourself, I hope you found this article useful. Please share if you think others will find it useful too!
Please check out more posts on the TAB Engineering blog and follow me on Twitter for more of the same. If youâre interested in joining our talented and passionate iOS team, then please message me!