11 Tips To Become A Better Swift Developer

Posted on - Last Modified on

Have you been programming in Swift for a while and aiming to be better at it? You're at the right place! These tips, if followed wholeheartedly, shall take you a step ahead in Swift Programming.

Feel free to copy and paste the code snippets into Playground. To make it easier for you to understand, I have included several YouTube video links as part of the explanations.

1. For Loop vs. While Loop

Let’s take the below code which prints “Hello” 5 times as an example.

var i = 0
while 5 > i {
    print("Hello")
    i += 1
}

You initialized the variable “i” and incremented it once after each iteration to ensure that the text is printed the exact number of times you want it to. What if I say you are better without it?

for _ in 1...5 {
    print("Hello")
}

The above code does the same task but without any variables.

Rule of Thumb: The greater the number of variables your code has, the higher the chances of code bugs! Never forget the Butterfly effect. It is always better to follow the KISS Methodology (Keep It Simple, Stupid!).

YouTube Life Vest: For Loop Tutorial

2. Functional Programming

Functional programming can make you look smarter in the programming world. Have a look at the snippet below.

var newEvens = [Int]()
for i in 1...10 {
    if i % 2 == 0 {
        newEvens.append(i)
    }
}
print(newEvens) // [2, 4, 6, 8, 10]

It is a simple program printing all the even numbers between 1 and 10: an age-old imperative approach to coding. Want to see the beauty of functional programming? Here it is:

var evens = Array(1...10).filter {
    $0 % 2 == 0
}   
print(evens) // [2, 4, 6, 8, 10]

That’s way simpler and better

3. Enum Type Safe

The very first tip said the lesser you write, the easier your life. When it comes to switching statements, for example, introducing enums can be a life saver. For example:

switch person {
    case "Adult":
        print("Pay $7")
    case "Child":
        print("Pay $3")
    case "Senior":
        print("Pay $4")
    default:
        print("Bad Choice!")
}

Here, you are hard coding the values for each case — Adult, Child, and Senior. Let's now see how enums can add beauty to your code.

enum People {
    case adult, child, senior
}
var person = People.adult
switch person {
    case .adult:
        print("Pay $7")
    case .child:
        print("Pay $3")
    case .senior:
        print("Pay $4")
}

The chances of you making a mistake are highly reduced with enums.

YouTube Life Vests:

1.      Switch Statement Tutorial

2.      Enums Tutorial

4. Optional Unwrapping

Nested statements can be a nightmare — an endless staircase of complex code! This is where the guard statement comes to the rescue. It can check one or more condition in a single statement, and if any condition is not satisfied, an else block will be called which transfers the control of the program.

Have a look at the clutter that the nested statement causes.

var myUsername: Double ?
    var myPassword: Double ?
        func userLogIn() {
            if let username = myUsername {
                if let password = myPassword {
                    print("Welcome, \(username)"!)
                }
            }
        }

Guard statement, on the other hand, makes it a lot cleaner:

func userLogIn() {
    guard
    let username = myUsername,
        let password = myPassword
    else {
        return
    }
    print("Welcome, \(username)!")
} 

Pretty, isn’t it?

5. Generics

Code reusability is the key to be a better programmer. Generics come in handy when avoiding duplication and providing reusable pieces of code. Let’s go through the below code fragments to understand the difference between a redundant code and a code with no duplication.

var stringArray = ["Bob", "Bobby", "SangJoon"]
var intArray = [1, 3, 4, 5, 6]
var doubleArray = [1.0, 2.0, 3.0]
func printStringArray(a: [String]) {
    for s in a {
        print(s)
    }
}
func printIntArray(a: [Int]) {
    for i in a {
        print(i)
    }
}
func printDoubleArray(a: [Double]) {
    for d in a {
        print(d)
    }
}

Example 1

func printElementFromArray < T > (a: [T]) {
    for element in a {
        print(element)
    }
}

Example 2

func printElementFromArray < T > (a: [T]) {
    for element in a {
        print(element)
    }
}

Example 2 shows you how simply can you write a program to perform a certain action without unnecessarily introducing so many lines of duplicate code, as evident in Example 1.

YouTube Life Vest: Generic Tutorial

6. Extension

Suppose you were writing a program to print the square of a number. The chances are high that you end up with something which looks like :

func square(x: Int) - > Int {
    return x * x
}
var squaredOFFive = square(x: 5)
square(x: squaredOFFive) // 625

One simple rule to making your life easier: lesser typing equals lesser errors, equals working code, equals your happiness!

Get rid of the unnecessary variables as much as possible:

extension Int {
    var squared: Int {
        return self * self
    }
}
5. squared // 25
5. squared.squared // 625

Short and simple!

YouTube Life Vest: Extension tutorial

7. Computed Property vs. Function

The more connected your code is, the lesser typing, typo mistakes, and errors you will have to remedy. If your code has parts which can be interdependent, do not introduce unnecessary mutually exclusive lines of code. Keep it as much connected as possible.

func getDiameter(radius: Double) - > Double {
    return radius * 2
}
func getRadius(diameter: Double) - > Double {
    return diameter / 2
}
getDiameter(radius: 10) // return 20
getRadius(diameter: 200) // return 100
getRadius(diameter: 600) // return 300

Here, radius and diameter can be interdependent but still have two mutually exclusive getters for no reason at all! Let’s look at a better version:

var radius: Double = 10
var diameter: Double {
    get {
        return radius * 2
    }
    set {
        radius = newValue / 2
    }
}
radius // 10
diameter // 20
diameter = 1000
radius // 500

Life sorted!

8. Defer

A defer block contains code which will be called only when all the other code in the current scope has ended execution. It “defers” the code execution to a certain point. This is a cleaner approach and helps reduce redundancy.

For example :

func process(fileName: String) throws {
    if exists(fileName) {
        let file = open(fileName)
        defer {
            close(file)
        }
        let userName = getUserName()
        guard userName != ""
        else {
            return
        }
        file.write(userName)
        let userAge = getUserName()
        guard userAge >= 18
        else {
            return
        }
        file.write(userAge)
        // close(file) is called here, at the end of the scope.
    }
}

9. Nil Coalescing

The Nil Coalescing operator is a ternary operator that you can use in your code while working with arbitrary values.

For instance, the user choosing a theme color for Twitter:

var userChosenColor: String ?
    var defaultColor = "Red"
var colorToUse = ""
if let Color = userChosenColor {
    colorToUse = Color
} else {
    colorToUse = defaultColor
}

Always dread long code! They will kill your happiness.

Here is how Nil Coalescing works:

var colorToUse = userChosenColor ? ? defaultColor

If the userChosenColor is nil, it assigns the
default color.

 10. Closure vs. Function

Function name, variables, return types, etc, etc… Too much to handle, right? But imagine this — with Closures, you would only have to remember one thing.

A program with a normal function definition would look similar to the one below:

func sum(x: Int, y: Int) - > Int {
    return x + y
}
var result = sum(x: 5, y: 6) // 11

And this is how it would look like with Closures:

var sumUsingClosure: (Int, Int) - > (Int) = {
    $0 + $1
}
sumUsingClosure(5, 6) // 11

You just need to remember the variable name. Pretty awesome!

YouTube Life Vest: Closure Tutorial

11. Conditional Coalescing

You can very well use the nil coalescing ternary operator for condition based programming as well.

The below code fragments will make it easier for you to understand.

var currentHeight = 185
var hasSpikyHair = true
var finalHeight = 0
if hasSpikyHair {
    finalHeight = currentHeight + 5
} else {
    finalHeight = currentHeight
}

Unwanted clutter! Let’s clean it up :

finalHeight = currentHeight + (hasSpikyHair ? 5 : 0)

If hasSpikyHair will be true, 5 will be added to the currentHeight else 0 will be added. Simply and tidy.

 

Do you think you have some hooks which can uplift the skills of other Swift Developers? Why not share it in the comments section below!

Posted 5 July, 2017

Ruchi Bhargava

Content Writing | Designing | Web Development

Hi! Are you looking for content that gets all the birds (read: customers) in one proverbial stone? Then I'm the person you need to talk to. After millions of words written for my clients, I can guarantee one thing: quality. When you're working with me, you'll get nothing short of perfect, well-researched, and enticing content. But that's not all I'm about. Along with creating custom cont...

Next Article

The 11 Jobs Robots Will Take First