SECRET OF CSS

I Roasted My First iOS Apps’ Source Code and Refactored It | by Ricardo Montemayor | Aug, 2022


Tips for iOS developers

0*ay1imfTGwq48fI0B
Photo by Kelly Sikkema on Unsplash

Just found an HDD with all of my old coding projects. I wanted to take a look, and share the atrocities I committed, so I roasted my code after developing a better alternative.

I started my iOS development journey when I was finishing high school in 2018. There was a full year dedicated to just following tutorials, learning the semantics of the language, and half-baked projects. I’ve decided to skip those and go straight into my first, fully independent apps.

This was my first real iOS application. My creation without following a tutorial.

I remember I had just learned web scraping using Python. I was very excited to apply it somewhere. I decided to make an animal encyclopedia, or Animalpedia for short, as an iOS application.

1*bMIoMs8nV3FgiBvphwncCQ
Animalpedia demo

The first thing I noticed whilst opening the project was that there were no external API calls. Of course not. I had no clue how to make network calls during this time.

For those new, an API is a way to communicate with a service. So imagine there is a Movies API. You tell the API, “Give me all horror movies,” and the API will retrieve and give you all the horror movies data.

I learned how to web scrape using Python, so I made a script that generated a JSON file with all the animals’ data. After that, I manually imported it to the project.

Giant JSON with all known existing animals

The same thing goes for the images. I did not know you could retrieve the image from a URL, so I included them as Assets.

1*yrdGWeNFWOQOec4SEp9nVg
Images of all known existing animals

I could argue that I was playing it safe by not being dependent on an external provider, but I’ll be lying. The truth is that I had no idea what an API was or how to retrieve images over the internet in an iOS application.

It was also my first time creating an app icon. I assume I got a little bit overwhelmed by the sheer number of images with different dimensions you needed to include, so I just added the icon that appeared on the Home Screen.

1*fASEa8OKFRvpz76RUu7hrA

In the most recent WWDC, Apple announced that in Xcode 14, you would no longer need to include all different icon sizes, just one. However, this is just recent news.

If you need a free third-party solution for generating all the different icon sizes, I recommend going over to appicon.io. Just upload your 1024x1024 app icon and it will generate all the different sizes so you can just drag and drop them into your project.

1*lSYXy1d MSHZGGUo YXwsg

Fancy. I also showed a custom launch screen for the first time!

1*t1EvfggVVdjDYywQM7dDWQ
Showcase of the App Icon and the Launch Screen

Okay, let’s take a look at the actual project structure. There’s the AppDelegate.swift, aMenuViewController.swift that has nothing inside, a strangely named AnimalsTableViewControllertest2.swift( I did not know how to refactor/rename files after creating them), and other files.

Quick tip: to rename a class, right-click the class name, Refactor>Rename

1*OtRsNVskEUm0gyCNovudNw
Not-so-good project structure

If you are starting, note that a project structure should not look like this. They should be grouped by their responsibilities, like this:

not-so-good structure— animalpedia, appdelegate, models, views, controllers, JSON, assets, launchscreen, info… better structure — animalpedia, animalpedia, appdelegate, models, animal, view, main, controllers, menuviewcontroller, animalviewcontroller, animalstableviewcontrollertest2, JSON, animals, assets, launchscreen, info
Good project structure

To properly structure your project, you first need to read about architectural patterns. They might seem intimidating initially, but they’ll guide you to solve common problems. There are many different patterns, but keep it simple:

  • If you are using UIKit (Storyboards) go for MVC
  • If you are using SwiftUI go for MVVM

After taking a look at AnimalsTableViewControllertest2.swift, I realized it is the main UITableViewController you can see in the demo.

I created two arrays of type Animal; one for all animals and one for filteredAnimals (filtering meaning the user typed on the search bar on top).

I’ve noticed that I enjoy typing a lot of code twice in my old projects, like in this case. It never crossed my mind there might be something sketchy about duplicating code. For me, it was a great indicator that I was going on the correct path! Wrong!

Quick tip: If you are typing your code twice, there is always a better approach.

I also had no clue what ternary operators were. I relied heavily on if-else statements even if they had one line.

stop using if-else if you are increasing complexity! instead use return isFiltering() ? filteredAnimals.count : animals.count

I did not know about the existence of computed properties. I went for functions that returned the property I needed.

Old code example

Let’s fix that. I refactored those functions into computed properties.

Good code example

Quick tip: Try to use computed properties whenever you do not need to pass parameters.

Also, I removed the comment.

// Returns true if the text is empty or nil

I used to do this a lot. Commenting on the most trivial things. Good code is self-explanatory. The property searchBarIsEmpty is self-explanatory. I do not need to know more about it or how it is calculated.

Unnecessarily, I also left too many spaces in random places of the code.

This makes the code messy and hard to read, so try using new lines conservatively.

A units converter app. I dedicated this app to my dear mother as she was looking for a unit converter app that was easy to use (most of the existing ones were too complicated). I dedicated two days of development and came up with this:

1*kK5J3NbvSy HB971B T9Rw
Demo for Easy Convert

This was an app that made me confident enough to submit it to the App Store. Since then, it has gone through some iterations. I remade it in SwiftUI (stay tuned, I will make a tutorial soon).

You can find it here if you are interested to see what the app is like now.

Even if it was fully functional, the code itself is atrocious, to say the least; I cannot believe it runs.

During this time, I adopted a philosophy of finishing projects. Not aiming for perfection but for good enough. That’s a great philosophy I believe everyone should adopt. You can always iterate and improve.

This project was far from perfect but did its job — it easily converted units.

Okay, let’s see the code.

I just opened the ViewController.swift file and am already cringing. I created arrays of Strings for each unit category.

I think I know where this is going… I will use these literal Strings as if they were enums.

Quick tip: Do not use Strings for different cases! Make a custom enum with all the possible cases. Use the CustomStringCovertible protocol if you need the enum’s String.

The Unit class

Just found a Unit class.

1*tbb gJLA3Yh61KimYSHnbg

My first concern is that Apple already has a fully functional and finished Unit class in its Foundation library. I ignorantly decided to replace it with my own.

1*zD8admAXz15cCHEEk3VrVg

I probably did not know about its existence. Nevertheless, I find it funny that I did not bother finding an existing solution (like we all lazy developers do) and went straight into implementing my own.

Quick tip: There probably exists a solution for your problem. You just need to Google hard enough.

I made a custom initializer for creating a unit.

To create an instance of my custom Unit, you need to pass a category of type UnitCategory (an enum that includes .length, .volume, etc.) and… there it is, a unit of type String.

Very bad code

I had to cut most of the initialization code, but there are another 200 lines of switch statements for the other units.

Interestingly and weirdly enough, my Unit class contains a property named toMeter even though the class should work for any dimension, not just length.

I’m assuming I did length units first and needed a base coefficient all units in that dimension could relate to for conversions and just did not bother renaming toMeter later on.

1*g11i4qrpA zkd1uvuFR0Kg
How to do linear conversions

I complicated everything with this implementation. In reality, Apple already has Unit, Measurement, and Dimension classes that do all this work for us. Look at how simple it is.

I created a convert function. You pass three parameters: a value, an input unit, and an output unit.

That’s it, two lines of code to convert units.

There’s a great article for converting units in Swift. You can find it here.

I’ve created a much better approach for getting the arrays of units for each dimension type. No need to create extra classes. The enum will suffice.

Good code example

I wanted to share more of my old code bases, but I think this article has extended enough. I hope you learned a thing or two about the not-so-good practices when developing iOS apps.

1*FStftyucv6Qpaw jI9IagA

Thanks for reading, and I wish you the best!



News Credit

%d bloggers like this: