iOS – Are 20 Quick Valuable Concepts Best way to Learn Swift?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (Are 20 Quick Valuable Concepts Best way to Learn Swift? ).

In this article, We will discuss 20 quick valuable concepts which is the best way to learn swift and helps to build iOS applications. We’ll need Swift Foundation Concepts as we start building apps. It means that we introduce each topic in a way. This provides enough background to understand the foundation concepts.

A famous quote about learning is :

The beautiful thing about learning is that nobody can take it away from you.

So Let’s begin.


1. Hello World

It is common to start any tutorial for a new language with the Hello World example so we’ll start out by showing how easy this is to do in Swift:

print("Hello World!")      // Prints "Hello World!" to the output window in Xcode

To make this a little more personal, let’s look at one of the handy features of Swift (called string interpolation) where we can insert values into strings using the \(...) syntax. Below, we’ve inserted name into the middle of our string:

let name: String = "World"
print("Hello \(name)!")     // Prints "Hello World!"


2. When to use let vs var

We’ll notice in the example above we’ve used let to create the new variable for the name “Bob”. In Swift, we’ll choose from the following 2 options when creating a new variable:

  • let => Use let when we are defining a constant (a value that will not change)
let numberOfContinents: Int = 7   // Seven continents will not change so we've used "let"
  • var => Use var when we are defining a variable (a value that might change)
var continentsVisited: Int = 2   // Continents visited increases over time so we've used "var"

In general, it is considered a best practice to use constants (let) whenever possible.


3. Numbers

The two most common types of numbers we’ll use in Swift are integers (Int) and doubles (Double):

Integers are whole numbers with no fractional component:

let minValue: Int = -42
let maxValue: Int = 55 

Doubles can have a fractional component:

let pi: Double = 3.14159
let billAmount: Double = 10.25


4. Strings

Strings represent a series of characters:

let hello: String = "Hello"
let world: String = "World"

We can use string interpolation to construct new strings:

let helloWorld: String = "\(hello) \(world)"    // "Hello World"

Or we can use the + operator to combine strings:

let helloWorld: String = hello + " " + world    // "Hello World"


5. Booleans

Boolean is a very simple type in Swift as it can only ever be true or false:

let swiftIsCool: Bool = true
let iMissObjectiveC: Bool = false 


6. Arrays

Arrays store a list of values that must be of the same type. Below we’ve kept track of the previous bill amounts (which is a list of doubles):

// Notice how we've used "var" here since we want to append new items to the array
var previousBillAmounts: [Double] = [10.25, 21.32, 15.54]

To add a new bill to the array:

previousBillAmounts.append(52.45)    // Result: [10.25, 21.32, 15.54, 52.45]

To check on how many bills there are in the array:

let count = previousBillAmounts.count            // Result: 4

Or to check the first bill amount in the array:

let firstBillAmount = previousBillAmounts[0]    // Result: 10.25


7. Dictionaries

Much like we might use a real-world dictionary to look up the definition for a word, you can use the dictionary data structure in Swift to create associations between keys (the word in the real-world dictionary) and values (the definition in the real-world dictionary).

For example, let’s say we want to keep track of the ages of people that are using our app. This will best done using the following dictionary:

var people: [String: Int] = [
                              "Bob": 32,
                              "Cindy": 25
                            ]

Here, the key is the name of the person and the value is the person’s age.

Later on if we want to find out Bob’s age, we can look it up by doing:

let bobsAge = people["Bob"]

If we get a new user we can easily add them to our dictionary using the following syntax:

people["Dan"] = 56


8. Specifying Types

In most of the examples in this article, we are explicit with the types of our constants and variables. Explicit typing looks something like:

let name: String = "Bob"   // Explicitly designating "name" to be of type "String"

However, Swift is smart enough to infer the type for us in a lot of cases. The short example of previous example is:

let name = "Bob"   // Swift infers "name" is of type "String" since "Bob" is a String

In cases where Swift can infer the type, it’s not necessary to be explicit with the types for our constants and variables. We just do it in this guide so that the examples are easier to follow.


9. Any and AnyObject

Swift has two special “catch all types” that come in handy when a more specific type cannot determine.

  • AnyObject can represent an instance of any class type.
  • Any can represent an instance of any type at all.

In general, it’s a best practice to be as specific with our types as possible and avoid the use of AnyObject and Any, but they become particularly helpful when interacting with Objective-C code that is less strict on typing.


10. Optionals

Optionals is a very important concept in Swift and it means to improve the safety of Swift code. By simply placing a question mark (?) after any type, it declares that variable to be optional. An optional type allows that variable to exist in one of the following two states:

  1. There is a value and it equals x
  2. There isn’t a value at all

Let’s look at an example to make this more clear. Consider the following 2 examples where we are trying to convert a String to an Int:

// Example 1 (Conversion succeeds)
let input: String = "123"
let optionalConvertedInput: Int? = Int(input)  // optionalConvertedInput = 123

// Example 2 (Conversion fails - input is not a number)
let input: String = "123abc"
let optionalConvertedInput: Int? = Int(input)  // optionalConvertedInput = nil

Swift requires optionalConvertedInput to be of type Int? (or “optional Int”) so that it is explicit that convertedInput might not contain a value (in the case when the conversion fails). If we were to declare convertedInput as simply Int, we’d get a compile error.

There’s a handy syntax in Swift that we’ll use quite often when working with optionals. If we wanted to use the value of optionalConvertedInput later on in our code, we’d have to first check to make sure it’s not nil. We can do so using the following code:

if let convertedInput = optionalConvertedInput {
   // Code that gets executed when optionalConvertedInput is NOT nil
} else {
   // OptionalConvertedInput IS nil, do something else
}

In other languages like Java, NullPointerException is a common source of crashes. This exception fires when a null reference accesses. Swift’s Optionals go a long way to reduce this type of programming error.


Optionals in string interpolation

When using optionals in string interpolation, the value with either be Optional(...) or nil without being explicitly unwrapped. When the inner value needs, the optional must unwrap.

let maybeString: String? = "value"

print("\(maybeString)")  // prints -> Optional("value")
print("\(maybeString!)")  // prints -> "value"


11. Functions

Functions in Swift are very similar to other languages. The simplest function in Swift can write as:

// This prints "Hello!" to the output window
func printHello() {
    print("Hello!")
}

// Calls this function
printHello()

We can extend this function to be a little more personable by taking in a name and returning the greeting instead of printing it out:

// Takes in a "personName" parameter of type String and returns the greeting as a String
func sayHello(personName: String) -> String {
    // Implicitly returns when there is a single statement
    "Hello \(personName)!"
}

// Calls this function
let greeting: String = sayHello("Bob")

Things get a little more interesting when we start to have multiple parameters as Swift has the concept of external and local parameter names. An external parameter name is used to label arguments passed to a function call. A local parameter name is a name used in the implementation of the function.

// "to" + "and" are the external parameter names
// "person" + "anotherPerson" are the local parameter names
func sayHello(to person: String, and anotherPerson: String) -> String {
    "Hello \(person) and \(anotherPerson)!"
}

// Calls this function using the "external" parameter names
let greeting: String = sayHello(to: "Bill", and: "Ted")


12. Control Flow


Conditional Statements

If statements are very similar to other languages and can express as:

let temperatureInFahrenheit: Int = 90

if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}


Loops

The two most common types of loops we’ll need in Swift are for loops and for-in loops.

For loops work well when we want to do something until a particular condition is met (in the case below until index >= 3):

// Simple for loop that prints "Hello" 3 times
for var index = 0; index < 3; index++ {
    print("Hello")
}

C-style for loops deprecated and will remove in future versions of Swift. For-in loops are preferred instead. The above example could be re-written as:

for _ in 0..<3 {
          print("Hello")
      }

For-in loops come in really handy when we want to do something to each item in a collection (such as an array):

let names = ["Anna", "Alex", "Brian", "Jack"]

// Loops over each name in "names" and prints out a greeting for each person
for name in names {
    print("Hello, \(name)!")
}

Sometimes, we want to loop over each item in an array and also keep track of the index of the item. Array’s enumerated() method can help you achieve this:

let names = ["Anna", "Alex", "Brian", "Jack"]

for (index, value) in names.enumerated() {
    print("Item \(index + 1): \(value)")
}


13. Classes

Classes are the building blocks of our app’s code. We define properties and methods to add functionality to our classes by using the same syntax as for variables and functions.

Below we can find a Person class that is meant to show an example of the types of things we’ll want to do when building our classes.

class Person {
	
    // Custom initializer - takes in firstName and lastName
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName

        // Increment type property each time a new person is created
        Person.numberOfPeople++
    }
	
    // *** Properties ***
	
    // Stored Property - Stored as part of the current instance of the class
    var firstName: String
    var lastName: String

    // Computed Property - computes "fullName" from "firstName" and "lastName"
    var fullName: String {
    	get {
            "\(firstName) \(lastName)"
    	}
    }

    // Type Property - Single instance for all instances of the class,
    // similar to a static property in Java
    static var numberOfPeople = 0   
    
    // *** Methods ***
    
    // Instance Method
    func greet() {
    	// Notice the use of "self" - self refers to the current instance and 
        // is similar to "this" in Java
    	print ("Hello \(self.firstName)")
    }
    
    // Type Method
    class func printNumberOfPeople() {
    	print("Number of people = \(Person.numberOfPeople)")
    }
}

// ... Using the Person Class ...

// Create a new instance of the Person class
let bob = Person(firstName: "Bob", lastName: "Smith")

// Call instance method
bob.greet()   // Prints "Hello Bob"

// Accessing properies
print("Bob's first name is: \(bob.firstName)")  // Prints "Bob's first name is: Bob"
print("Bob's full name is: \(bob.fullName)")    // Prints "Bob's full name is: Bob Smith"

// Call type method
// Prints "Number of people = 1" (since we've only created one Person)
Person.printNumberOfPeople()


14. Protocols

Protocols are similar to interfaces in other languages. Think about a protocol as a contract. The contract includes a set of methods that must be implemented. Any classes that choose to implement a protocol sign this contract and implement all the methods that are in the protocol.

Let’s say we have the following protocol (MyFriendlyGreeterProtocol) that defines 2 methods sayHello() and sayBye():

protocol MyFriendlyGreeterProtocol {
    func sayHello()
    func sayBye()
}

Any classes that implement this protocol (you implement a protocol by adding its name after the class defintion as shown below), must implement both of these methods:

class MyEnglishPerson: MyFriendlyGreeterProtocol {
    func sayHello() {
        print("Hello!")
    }

    func sayBye() {
        print("Bye!")
    }
	
    // ... other methods for this class ...

}

class MySpanishPerson: MyFriendlyGreeterProtocol {
    func sayHello() {
        print("Hola!")
    }

    func sayBye() {
        print("Adios!")
    }
	
    // ... other methods for this class ...
}

There is a lot more you can do with protocols as they form one of the key design patterns in iOS. The code above merely shows how to get started with the syntax for protocols.


15. Swift Closures

Closures are self-contained blocks of code that can be passed around and used in our code. These are similar to blocks in Objective-C and lambdas in other programming languages.

Swift Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as “closing” over those constants and variables. Swift handles all of the memory management of capturing for you.

Closure Example:

Example: A function called makeIncrementer which contains a nested function

Here’s an example of a function called makeIncrementer, which contains a nested function called incrementer. The nested incrementer() function captures two values, runningTotal and amount, from its surrounding context. After capturing these values, incrementer is returned by makeIncrementer as a closure that increments runningTotal by amount each time it is called.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

The return type of makeIncrementer is () -> Int. This means that it returns a function, rather than a simple value. The function it returns has no parameters, and returns an Int value each time it is called.

The makeIncrementer(forIncrement:) function defines an integer variable called runningTotal, to store the current running total of the incrementer that will be returned. This variable is initialized with a value of 0.

The makeIncrementer(forIncrement:) function has a single Int parameter with an external name of forIncrement, and a local name of amount. The argument value passed to this parameter specifies how much runningTotal should be incremented by each time the returned incrementer function is called.

makeIncrementer defines a nested function called incrementer, which performs the actual incrementing. This function simply adds amount to runningTotal, and returns the result.

When considered in isolation, the nested incrementer() function might seem unusual:

func incrementer() -> Int {
    runningTotal += amount
    return runningTotal
}

The incrementer() function doesn’t have any parameters, and yet it refers to runningTotal and amount from within its function body. It does this by capturing a reference to runningTotal and amount from the surrounding function and using them within its own function body. Capturing by reference ensures that runningTotal and amount do not disappear when the call to makeIncrementer ends, and also ensures that runningTotal is available the next time the incrementer function is called.

Example: a function called makeIncrementer in action

Here’s an example of makeIncrementer in action:

// This example sets a constant called incrementByTen to refer to an //incrementer function that
// adds 10 to its runningTotal variable each time it is called.

let incrementByTen = makeIncrementer(forIncrement: 10)

incrementByTen()  // returns a value of 10
incrementByTen()  // returns a value of 20
incrementByTen()  // returns a value of 30


16. Type Casting (as, as?, as!)

Type casting changes the type of a particular instance to another compatible type. There are 3 ways to accomplish this with Swift:

  1. Guaranteed conversion with as : This is the safest cast. It will never fail since the compiler can guarantee the cast will work. Use this when you are upcasting from a child class to its parent or doing something like 1 as Float.
// Guaranteed conversion as the compiler can verify this will succeed
let myFloat = 1 as Float

// Guaranteed conversion as upcasting from a type to its parent type is safe 
// UIView is a parent of UITableView
let myView = myTableView as UIView

2. Conditional conversion with as? : This is a cautious cast. If the cast fails, it will return nil. This is needed when downcasting from a parent type to a child type.

// If myView is actually a tableView, the downcast will succeed, otherwise it will fail safely
if let myTableView = myView as? UITableView {
    print("The downcast succeeded!")
} else {
    print("The downcast failed!")   	   
}

3. Forced conversion with as! : This is a dangerous cast that you should avoid using. If the cast fails, this will crash our app. Use this cast carefully.

// DANGEROUS: If myView is actually a tableView, the downcast will succeed
// Otherwise it will crash the app
let myTableView = myView as! UITableView


17. Understanding the Exclamation Mark (!)

There are various places you might come across an exclamation mark in Swift code. The following examples are meant to capture the major types of use cases for the exclamation mark operator that can cause confusion when first learning Swift.

When getting the actual value out of an optional (called unwrapping an optional):

let possibleString: String? = "An optional string."

// DANGEROUS: possibleString must NOT be nil or this will crash
let forcedString: String = possibleString! 

// SAFE: Will only enter the if clause if possibleString is NOT nil
if let actualString = possibleString {
    // do something with actualString
}

// SAFE: Generally preferred alternate syntax to "if let" that can exit early
guard let actualString = possibleString else {
    // exit early or throw exception
}
// do something with actualString

When type casting (called forced conversion):

// DANGEROUS: If myView is actually a tableView, the downcast will succeed
// Otherwise it will crash the app
let myTableView = myView as! UITableView

When defining variables that are initially nil but get set soon afterwards and are guaranteed not to be nil after that (called implicitly unwrapped optionals):

let assumedString: String! = "An implicitly unwrapped optional string."

// no need for an exclamation mark since assumedString is an implicitly unwrapped optional
let implicitString: String = assumedString


18. Property Observers

A very useful inclusion of the Swift language is Property Observers. While the language might sound complex, it’s actually a literal explanation of what it does. It allows you to observe properties and respond to impending or finished property changes. It’s part of Apple’s goal to make Swift a cleaner language because a developer merely has to keep any logic related to updating properties in one convenient place.

Let’s look at an example.

Assume we have a Fitness tracking application and whenever a user enters their weight, we calculate and display their BMI to them.

Without property observers, and keeping in good practice (since BMI is calculated and not set in initialization), we might have a class like this –

Swift

class Profile {
    let height: Double
    var weight: Double
    private var BMI: Double
    
    init(weight: Double, height: Double) {
        self.height = height
        self.weight = weight
        self.BMI = weight / (height*height)
    }
    
    func getBMI() -> Double {
        self.BMI
    }
    
    func updateBMI() {
        self.BMI = weight / (height*height)
    }
}  

In a view where we ask the user to enter their new weight, we would call profile.updateBMI() after the new weight is set. Isn’t this a little tedious? It’s almost a trap for developers. We have to actively remember that we should update our BMI every time we update our weight.

Thankfully, with property observers, we don’t have to actively watch every property change as a developer. Our class becomes –

class Profile {
    let height: Double
    var weight: Double {
        didSet {
            updateBMI()
        }
    }
    private var BMI: Double
    
    init(weight: Double, height: Double) {
        self.height = height
        self.weight = weight
        self.BMI = weight / (height*height)
    }
    
    func getBMI() -> Double {
        self.BMI
    }
    
    func updateBMI() {
        self.BMI = weight / (height*height)
    }
}  

It might not look like much, but now whenever we update BMI, we don’t have to worry about calling updateBMI() and to be honest, we can clean this up even more by making BMI private(set), changing Profile to a struct and adding a mutating func.

struct Profile {
    let height: Double
    var weight: Double {
        didSet {
            updateBMI()
        }
    }
    private(set) var BMI: Double
    
    mutating private func updateBMI() {
        BMI = weight / (height * height)
    }
}  

What is mutating we ask? Well, normally Struct’s are read only. This is because in order for them to be fast, they need to take up space on Stack instead of Heap. A simple way to explain this is to imagine that Stack is writing with a Pen and Heap is writing with a Pencil. Some of you might think “well what’s the big deal? they both write.” But think about all the extra work that comes with a Pencil – We need an eraser, we have to clean the eraser off the paper and can end up using more material if we edit a lot. A pen, on the other hand, we just write (we’re assuming you’re not using an erasable pen or white-out) and it’s set.

Mutating gives us the ability to say, “Hey, this Struct will be read-only, but if I make it a variable, I might want to update its properties, so please give me the ability to edit that Struct”.

There’s a little more to this under the hood, but Structs tend to be pretty thread-safe, so we can assume every Struct exists by itself and it’s pretty safe to edit like this.


Other Property Observers

There are other property observers for every stage of a state change – willSet, set/get are included. willSet has the added ability of being able to compare newValue to the original value (called the property name).

A few hints about where didSet can be quite powerful is when dealing with network data and data sources. When a user has the ability to get objects from a server with a regular network call, a search and tapping a keyword, it can be useful if the var dataSource: [Models] has didSet to reload the data of the view. That way we won’t have to do it manually.


19. Working with JSON

A lot of the time when working with REST API’s (like Instagram, Twitter, etc), the data that comes back will be JSON. JSON is a human readable data format (very similar to XML).

Below is an example of JSON that simulates the type of JSON. We might get back when using an endpoint that returns movies and their ratings:

  • An open curly brace means the start of a dictionary
  • An open bracket means the start of an array
{
    "status": "OK",
    "movies": [
        {
            "title": "Whiplash",
            "rating": 8.5
        }, 
        {
            "title": "Feast",
            "rating": 5.2
        }, 
        {
            "title": "Kung Fury",
            "rating": 7.1
        }
    ]
}


Below is an example of how we extract the movies and ratings from that response:

// data returned from the network response will typically be of type
// NSData (which is a buffer of bytes)
let responseData: NSData = // ... some value retrieved from the network response ...

// Wrap our code in a do catch as our code might throw an exception which we need to handle
do {
    // Start by converting the NSData to a dictionary - a dictionary for the entire response
    if let responseDictionary = try NSJSONSerialization.JSONObjectWithData(responseData,
        options:NSJSONReadingOptions(rawValue:0)) as? [String:AnyObject] {

            // Dip inside the response to find the "movies" key and get the array of movies
            if let movies = responseDictionary["movies"] as? [AnyObject] {

                // Get each movie dictionary from the array of movies
                for movie in movies {
                
                    // Use the movie "title" key and "rating" key to get their values
                    if let title = movie["title"] as? String {
                        if let rating = movie["rating"] as? Double {
                            print("Title:\(title), rating:\(rating)")
                        }
                    }
                }
            }
    }
} catch {
    print("Error parsing JSON")
}


20. Playgrounds

Xcode includes a very useful tool for learning Swift called “Playgrounds”. It’s very easy to create a new playground through Xcode.

Once inside a playground, we can write Swift code and see it run immediately (without needing to build and run a project each time). This allows you to try out different syntaxes and test out our code before including it in our app.

We highly recommend checking out Playgrounds while we are learning Swift.

That’s all about in this article.

Related Other Articles / Posts


Conclusion

In this article, We discussed 20 quick valuable concepts which are the best way to learn swift and help to build iOS applications.

Thanks for reading! I hope you enjoyed and learned about the 20 quick valuable Swift Foundation Concepts. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Loading

Summary
iOS - Are 20 Quick Valuable Concepts Best way to Learn Swift?
Article Name
iOS - Are 20 Quick Valuable Concepts Best way to Learn Swift?
Description
In this article, We will discuss 20 quick valuable concepts which is the best way to learn swift and helps to build iOS applications.
Author

1 thought on “iOS – Are 20 Quick Valuable Concepts Best way to Learn Swift?”

Leave a Comment