Let’s start by answering two important questions:

1- Who can read this article?

This article is for anyone who needs to learn more about iOS, anyone starting out in iOS development & for any iOS Developer looking to Upskill.

2- What you will learn?

  1. Functions
  2. Closures
  3. Classes & Structs
  4. Protocols
  5. Optionals

1- Functions

Functions are considered as blocks of code that you can “call” by just mentioning its name to perform a task and operation that is needed, functions can take parameters or cannot, you can also return a value or not as it depends on your code.

Functions usually have two parts

  1. Define the Function
  2. Call the Function

Every function has a function name, which describes the task the function will perform. To use a function we will call the function with its name and pass in arguments.

Let’s take a small example of a very simple function:

Let’s consider that you are a runner and you know that you can run 1 kilometre within 7 minutes. First, we write a function that calculates the number of kilometres that you can run per specific time.

countKilometers(totalTimeInMinutes: 100,timePerKilo: 7)

This line of code defines a function called countKilometers() which contains two variables or to be specific contains your parameters.

Let’s juggle your mind a bit, shall we?, Can you take an exam without taking the course work?, am sure your guess is as good as mine, which is a NO, you have to take the course work then take the exam, unless you want to fail. The same case applies to functions, you have to define the function first before calling it,

Let’s now answer this question, How do you define functions?

We will use our countKilometers function:

func countKilometers(totalTimeInMinutes: Int ,timePerKilo: Int) {      
     print("You run about \(totalTimeInMinutes/timePerKilo) kms")
}
countKilometers(totalTimeInMinutes: 100,timePerKilo: 7)

Output: You run about 14 kms

On the block of code above we; Define our function on the first two lines as;

func countKilometers(totalTimeInMinutues: Int ,timePerKilo: Int) {        
      print ("You run about \ (totalTimeInMinutes/timePerKilo) kms")
}

We will then call the function passing in 2 parameters;

countKilometers(totalTimeInMinutes: 100, timePerKilo: 7)

When we run our code above the output is 14. I figured you are somehow confused why the output is 14 and not 14.285714, to clarify this, our parameters are of Int datatype and not Float.

After doing this we discovered that our function can consist of

  1. Keyword called func
  2. Function name which is countKilometers
  3. Parameters “Optional” you can add them or not:
    3.1 first parameter: totalTimeInMinutes
    3.2-second parameter: timePerKilo
  4. Return type “we will mention it in the following section”
  5. {Function Body}

Now we will try to add a return type and use Float instead on Int as a data type for the parameters

func countKilometers(totalTimeInMinutes: Float ,timePerKilo: 
Float) -> Float {    
     return totalTimeInMinutes/timePerKilo    
     //    print("You run about \(totalTimeInMinutes/timePerKilo) 
     kms")
}
countKilometers(totalTimeInMinutes: 100,timePerKilo: 7)

Output: You run about 14.285714 kms.

Now you have the exact number of how many kilometres you ran, we used Float instead of Int data type. The print statement here is commented out as we already used the return statement to return our result.

Note: You can use // to make a single line comment or if you want multi line comments you can use this */ before the comments, and /* after finishing your comments, or you can mark all the lines you want to comment and press Command + /

So we tried to make a function with two parameters, let’s try to make a function without any parameters

func printPlayersNames(){    
   let playerNames = ["Mo Salah", "Messi", "Ronaldo", "Mane", "Ibrahimovic"]    
   print(playerNames)
}
printPlayersNames()

Output: [“Mo Salah”, “Messi”, “Ronaldo”, “Mane”, “Ibrahimovic”]

we can do the same function but by passing an array of strings as a parameter:

func printPlayersNames(playerNames: [String]){    
    print(playerNames)
}
let myPlayerNames = ["Mo Salah", "Messi", "Ronaldo", "Mane", "Ibrahimovic"]
printPlayersNames(playerNames: myPlayerNames)

Output: [“Mo Salah”, “Messi”, “Ronaldo”, “Mane”, “Ibrahimovic”]

Our output will still be the same in the two cases as all we did is just instead of letting the function without parameter and print an array of string in it we’ve added an array of String called playerNames as a parameter in the first line and then we initialized a constant and called it myPlayerNames in the third line then we passed it to our function in the last line.

You can also use Argument Labels.  Argument Labels are used when calling the function;

Let’s see an example of it and explain it in details:

func playGame(withPlayerName userName: String, andGameLevel 
gameLevel: String){    
      print("Welcome \(userName) in your first \(gameLevel) level")
}
playGame(withPlayerName: "Menaim", andGameLevel: "Hard")

Output: Welcome Menaim in your first Hard level

The advantage of using argument labels like withPlayerName and andGameLevel is that when you tried to call the function like in the last line you can see that we don’t have to add the parameters anymore, all we need to do is to use our argument labels like we did when we called the function.

You have to notice the difference between parameters and argument labels as argument labels are used more in coding as it is fairly common in practical iOS, and it’s easy to describe the function more than just passing the parameters, argument labels are also more descriptive for any function.

After speaking about functions and knowing everything about it, the questions now are :

  1. Why do we use functions?
  2. What are the benefits of functions?

If you have to go through 50 stairs about 5 times and each time you have to go up and down the stairs, concurrently you have an option that will make you go through these stairs for only one time, meaning, you will not need to go again for the remaining 4 times……what option would you pick?

The same with functions, if you have a block of code which may be repeated many times in your code, instead of increasing the lines of your code or repeating the same thing over and over, you can put this in a block of code in your function.


2- Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code.

Let’s elaborate this with a practical example:

func backward (_ S1: String, _ S2: String) -> Bool {    
    return S1 > S2
}
let names = ["Ahmed", "Mohamed","Rose","Maya","Noah"]
var arrangedNames = names.sorted(by: backward)
print(arrangedNames)

In the first line, we created a function called backward which has two String parameters called S1 and S2 and returns type Bool, we did use the closure, but as a function, we now have a sorting closure written as a function, after that, we initialized a String array called names and then we will use a function provided by apple called sorted(by:)

Output: [“Rose”, “Noah”, “Mohamed”, “Maya”, “Ahmed”]

Let’s check out other forms for closures:

let myNames = ["Ahmed", "Mohamed","Rose","Maya","Noah"]
var arrangedNames: [String] = []
arrangedNames = myNames.sorted(by:            
      { (S1: String, S2: String) -> Bool in    
   return S1 > S2
})
print(arrangedNames)

Output: [“Rose”, “Noah”, “Mohamed”, “Maya”, “Ahmed”]

The return value in this block of code is still the same, the beginning of the closure’s body is introduced by the in keyword. This keyword indicates that the definition of the closure’s parameters and return type has finished, and the body of the closure is about to begin, to clean our code even further we can remove something from the previous block, let’s figure out what we can chuck out and still maintain the functionality.

let myNames = ["Ahmed", "Mohamed","Rose","Maya","Noah"]
var arrangedNames: [String] = []
arrangedNames = myNames.sorted(by: {  s1, s2 in     
     return s1 > s2
})
print(arrangedNames)

Note: With Swift, you don’t even need to mention the data types of the parameters or the return type as Swift has the power to discover it by itself

sorted(by:) a builtin method in swift takes in two String parameters and returns Bool, In the sense that if you didn’t write them, by default swift will work with the original parameters, In this case, it will take s1 & s2 as Strings and then return type Bool

Here we can shorten our closure more and more but how can we do it? by using Shorthand Argument Names

let myNames = ["Ahmed", "Mohamed","Rose","Maya","Noah"]
var arrangedNames = myNames.sorted(by: { $0 > $1 } )
print(arrangedNames)

So why did we use $0 & $1, $0 and $1 refer to the closure’s first and second String arguments, which means that swift can provide you with a shorthand argument name to work with, meaning if you have more than two arguments we can use $0, $1, $2 and so on

There is an even shorter way to write the closure which we can use in “Operator Methods”

let myNames = ["Ahmed", "Mohamed","Rose","Maya","Noah"]

var arrangedNames = myNames.sorted(by: >)

print(arrangedNames)

So here we have used only (>) as a method that has two parameters of type String and returns type Bool.

We can also use Trailing closures which means we will pass our closure to the function as a parameter to be able to use and call it.

Note: Trailing Closures is the most useful and the most used.

func functionTakesAClosure(closure: () -> Void) {    
    // function body goes here
}

Here’s how you call this function without using a trailing closure:

functionTakesAClosure(closure: {    
     // closure's body goes here
})

Here’s how you call this function with a trailing closure instead:

functionTakesAClosure() {    
     // trailing closure's body goes here
}

so let’s apply it in our example:

let myNames = ["Ahmed", "Mohamed","Rose","Maya","Noah"]

var arrangedNames = myNames.sorted(){    

    $0 > $1
}
print(arrangedNames)

and while calling the function we don’t need even to write or use a pair of parentheses () after the function or method’s name

let myNames = ["Ahmed", "Mohamed","Rose","Maya","Noah"]
var arrangedNames = myNames.sorted { $0 > $1 }
print (arrangedNames)

you can use a function which takes two closures or more and in this case, we will use the trailing closure in the last one like the below:

Suppose we have   the function below loads a picture for a photo gallery:

All variables and DataTypes are undeclared, you will declare them in your code like “Server”, “Picture”, func download & someView

func loadMyPicture(from server: Server, completion: (Picture) -> 
Void, onFailure: () -> Void) {    
     if let picture = download("photo.jpg", from: server) {        
         completion(picture)    
     } else {        
         onFailure()    
     }
}

When you call this function to load a picture, you provide two closures. The first closure is a completion handler that displays a picture after a successful download. The second closure is an error handler that displays an error to the user.

let anyServer = Server()

loadMyPicture(from: anyServer) { picture in  
  
    someView.currentPicture = picture

} onFailure: {    

    print("Couldn't download the next picture.")
}

In this example, the loadMyPicture(from:completion:onFailure:) function dispatches its network task into the background, and calls one of the two completion handlers when the network task finishes. Writing the function this way lets you cleanly separate the code that’s responsible for handling a network failure from the code that updates the user interface after a successful download, instead of using just one closure that handles both circumstances.

You have to note that Closures are Reference types

func createIncrementer(forIncrement amount: Int) -> () -> Int {             
    var myTotal = 0    
    func incrementer() -> Int {        
         myTotal += amount        
         print(myTotal)        
         return myTotal    
    }    
    return incrementer
}

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

let addTenIncrementer = createIncrementer(forIncrement: 10)
addTenIncrementer() // return 10
addTenIncrementer() // return 20
addTenIncrementer() // return 30

and so on, which means that if we make a constant and called it, It’s supposed not to change, but because we are using closures which are a reference type the value of the constant will be changed in regards to calling the closure every time, as we did before, and to be sure the next step will prove it.

let addTenIncrementeragain = addTenIncrementer
addTenIncrementeragain() // return 40
addTenIncrementer() // return 50

which means that each one isn’t independent of the other but each one is dependent on the second one, as here we have 40 in addTenIncrementeragain() then we will have 50 in addTenIncrementer() which makes us pretty sure that closures are reference types, not value types.

we have another type of closures called Autoclosures, this type of closures is used when you want to unwrap an expression which is passed to the function as an argument, let’s take an example to be able to explain it:

var studentsQueue  = ["May", "Nolan","Haidy","Amal","Mohamed"]
print(studentsQueue)
// ["May", "Nolan","Haidy","Amal","Mohamed"]
let remove1stStudent = {studentsQueue.remove(at: 0)}
print(studentsQueue)
// ["May", "Nolan","Haidy","Amal","Mohamed"]
print("first student in line was \(remove1stStudent())")
// first student in line was May
print(studentsQueue)
// ["Nolan","Haidy","Amal","Mohamed"]

If we checked the last code, we would find that we used our closure at the third line in declaring our variable remove1stStudent. Despite removing the first element in the same third line, it still prints all the arrays. Even, when we called our closure at the fifth line we will discover that it prints the array without the first element, so we found that the variable remains as it is until the closure is fired.

Escaping Closures

A closure is said to escape a function when the closure is passed as an argument to the function but is called after the function returns.

This means that if you declare a function that takes a closure as a parameter, you can write @escaping before the parameter’s type, meaning that this closure is allowed to be skipped.

var completionHandlers = [() -> Void]()
func functionUsingEscaping(completionHandler: @escaping () -> Void) {    
    completionHandlers.append(completionHandler)
}

We have here a function; functionUsingEscaping() which takes a closure as its parameter and adds it to an array called completionHandlers, if we didn’t mark parameters of this function with @escaping this code will raise a compile-time error.

Note: Escaping closures can’t capture a mutable reference to self  for structures


3- Classes & Structs

The first and the most important thing you need to know is that class is a reference type and struct is value type. You introduce structures with struct keyword and classes with the class keyword.

Let’s start with syntax highlighting for each:

struct iOSCodeGuide {
	// Definition
}
class iOSCodeClass {	
        // Definition
}

Common Traits for both classes and structs

  1. Have properties and store values
  2. Both can adopt from protocols. “Protocols will be explained later”
  3. Have functions
  4. Have initializers

But classes have more traits than structs:

  1. Inheritance from other classes.
  2. Deinitializers to enable the instance to free the resources
  3. Allows more than one reference to a class instance

Here is a resource of videos and resolutions that may help, See the example below:

struct Resolution {    
    var height = 1280    
    var width =  720
}

class Video {    
    var name: String?    
    var fullHD = false    
    var resolution = Resolution()    
    var frameRate = 0.0

Note: Not all of these numbers are true, It’s just for the example, here we described a Resolution as a struct which has height and width and then created a class called Video which included an instance from the Resolution called resolution, name of the video which is String, fullHD which is a Bool and finally a frameRate which is a Float, and each one of them has its default value so I don’t need to create an initializer for them.

How can you check the value of the resolution or the value of anyone of them?

Here is how:

let video = Video()
print("video height is \(video.resolution.height)")
print("video width is \(video.resolution.width)")

Output:
video height is 1280
video width is 720

First, we will create an instance from our class which is video then we will get the resolution from this video, and finally we will access the width and the height for our video.

There is another way to check and print our width and height:

let myResolution = Resolution()
print("video height is \(myResolution.height)")
print("video width is \(myResolution.width)")

Output:
video height is 1280
video width is 720

This is the same as we did in the previous example, but the difference here is that we create an instance from the resolution struct itself and get the width and the height for it.

Let’s try getting the name of our video in the previous example:

print ("video name is \(video.name)")

It will give us a warning because name is an optional value, don’t worry if you don’t know what an optional value is, as it will be explained later so, for now, let’s work around the warning.

video.name = "Black Clover ep 50 "
print ("video name is \(video.name!)")

Output: video name is Black Clover ep 50

Now let’s create all of the properties for our video instance:

let video = Video()

video.name = "Black Clover ep 50 "
print ("video name is \(video.name!)")
//Output: video name is Black Clover ep 50 

video.resolution.width = 1080
print("video width is \(video.resolution.width)")
//Output: video width is 1080

video.resolution.height = 1920
print("video height is \(video.resolution.height)")
//Output: video height is 1920

video.frameRate = 60.0
print("video frame rate is \(video.frameRate)")
//Output: video frame rate is 60.0

video.fullHD = true
print("Is video quality is HD? \(video.fullHD)")
//Output: Is video quality is HD? true

And as we saw how we can access and update each property belongs to the class by just put . after the instance to be able to access its properties and update it.

Let’s try to prove that Struct is a value type and class is a reference type, starting by struct:

video.resolution.width = 1080
print("video width is \(video.resolution.width)")
//Output: video width is 1080

video.resolution.height = 1920
print("video height is \(video.resolution.height)")
//Output: video height is 1920

var resolution = Resolution()
resolution.width = 2800
print("width is \(resolution.width)")
//Output: video width is 2800

resolution.height = 1000
print("height is \(resolution.height)")
//Output: height is 1000

In the previous block of code, we have created an instance called resolution from struct Resolution and at the same time we’ve changed the values of the property resolution in the instance video, in the first 4 lines and after printing these values we discovered that each one has its own value and each one is separate from the other one in spite of being both under the same name which is resolution, but they are indecent from each other which proves that struct is a value type.

How are classes reference types?

var newVideo = video

newVideo.name = "One piece ep 900"
print("video name is \(video.name!)") 
//Output: video name is One piece ep 900

print("newVideo name is \(newVideo.name!)") 
//Output: newVideo name is One piece ep 900

In the previous code we created a new instance newVideo and made it equal to our old instance video, we then tried to give our newVideo a name in the second line and all we did is print the name of our old video and our newVideo which are exactly the same in spite of our old instance video’s name being “Black Clover ep 50” but now it has changed without doing anything to “One piece ep 900”  which makes us sure that classes are reference types and not value types.

As classes are reference types and not value types so when we tried to compare its values we cannot use ==  or != as usual but we use === for equality or !=== for inequality in Identity Operators.

var newVideoAgain = video
if newVideo === newVideoAgain {    
   print("Two instances are from the same main instance (video)")
}
else {    
   print("They are different")
}

Output: Two instances are from the same main instance (video)

In the previous code, we were just comparing between our two new instances which are both from the same main instance “video” that’s why we have the output which says that they are identical.

The last thing we will talk about in this section is pointers which are so easy to use in SWIFT comparing it with the different languages as in some other languages you need to put * to indicate that this is a reference but in SWIFT it’s treated like any variable or constant and already apple provides you with some pointers that you can use and you can check them from here


4- Protocols

Protocols are used to implement some codes or to be able to access something out of your class scope, protocols can be adopted by classes or structs and they come most of the time with a property called delegate.

Let’s start by defining the syntax first:

protocol myProtocol {    
    // Protocol definition
}

As I said before structs or classes, can adopt from one or more protocols:

struct myStruct: myProtocol {    
    // Struct definition
}

Or it can adopt from more than one protocol, that’s why I created another protocol to explain it:

protocol myProtocolII {    
    // Protocol defination
}
class myClass: myProtocol, myProtocolII {    
}

Protocols are used to add a specific task or property to a class or struct and it can also add if this property is settable or gettable:

protocol Sports {    
    var sportType: String {get set}    
    var numberOfPlayers: Int {get set}    
    func allDetails () -> String
}
protocol Club:Sports {        
    var clubName: String {get set}  
    var numberOfChampions: Int {get set}  
    var trainerName: String {get set}    
    var date: String {get set}
}
class Team: Club {        
    var clubName = "Al Ahly SC"
        
    var numberOfChampions = 9    
    
    var trainerName = "Pitso Mosimane"   
     
    var date = "Friday 27th November 2020"  
      
    var sportType = "Football"  
      
    var numberOfPlayers = 11    
    
    func allDetails() -> String {        
         let details = "\(clubName) won it's \(numberOfChampions)th CAF Champions League under the lead of \(trainerName) on \(date)"        
         print(details)        
         return details    
    }
}

let team = Team()
team.allDetails()

Output: Al Ahly SC won it’s 9th CAF Champions League under the lead of Pitso Mosimane on Friday 27th November 2020

In this previous code I have captured:

1- How you can create properties in your protocol and make it settable or gettable by writing {get set} beside it.

2- How to implement inheritance between two protocols as I’ve created the Club protocol and made it inherit from the Sports protocol. i.e When some protocol inherits from another one, it takes all of its properties.

3- Class Team conforms from Club protocol and we will notice that if you write only the first line which is: class Team: Club { } it will give you some errors and the reason is you have to add all variables and functions which are existing in your protocols: Club and Sports in your Team class.

Why do I need to write all functions and variables in this class despite conforming from only one protocol which is Club, as the Club protocol already inherited from Sports protocol which made it inherit all its properties and functionalities as we said before.

In the end, we’ve created an instance from our Team class and called its function, which brought us the print statement.

And also you can use your protocols as Types which means that you can use it as:

  • Constant, variable or property
  • Function, method or initialize as a parameter or return type
  • Arrays, dictionaries or other containers as items
protocol RandomNumberGenerator {    
     func random() -> Double
}
class Dice {    
     let sides: Int    
     let generator: RandomNumberGenerator    
     init(sides: Int, generator: RandomNumberGenerator) {        
          self.sides = sides        
          self.generator = generator    
     }    
     func roll() -> Int {        
          return Int(generator.random() * Double(sides)) + 1    
     }
}

The previous example was provided by SWIFT and explains how you can create a protocol and then make it a type as we created RandomNumberGenerator and then made a variable from this type called generator.

There is another benefit for protocols called Protocol Composition which means that the struct or the class can adopt from more than one protocol.

Here is an example:

protocol Name {    
    var myName: String { get }
}
protocol Age {    
    var myAge: Int { get }
}
struct Person: Name, Age {    
    var myName: String        
    var myAge: Int
}
func wishHappyBirthday(to celebrator: Name & Age) {    
    print("Happy birthday, \(celebrator.myName), you're \(celebrator.myAge)!")
}
let birthdayPerson = Person(myName: "Menaim", myAge: 23)wishHappyBirthday(to: birthdayPerson)

Output: Happy birthday, Menaim, you’re 23!

SWIFT provided this example, and if you noticed something it would be that it’s like we did before in protocols inheritance, but the difference here is instead of doing the inheritance, I’ve made the struct adopt from our two protocols, and while creating the function I’ve passed a parameter which needs to be from both protocols: func wishHappyBirthday(to celebrator: Name & Age) {}

This means that any type conforms from these two protocols can be used in this function, and that’s why I’ve created an instance from Person which adopts both two protocols and then uses it in my function.

The last thing you need to know about protocols is delegation; It’s an important feature because it helps to access some properties, variables or functions which can be out of the class scope, for example:

If you have a toDoList App and you clicked on this button like the image:

It directs you to another viewController:

So in this one, you need to fill the task title textField to be able to show it in the first one like in the images:

The main goal here is how you can take this text you have written in the textField and show it at the other viewController without facing any issues, as both controllers have no access to each other, that’s why you need to use Protocols & Delegates to pass this issue.

Suppose you have a class called Model and in this class, you need to fetch all the videos to be able to show them in another controller we will do this:

In class Model we will create our protocol:

protocol ModelDelegate {        
    func videosFetched (_ videos: [Video])    
}

and here in my Model class, I will create a delegate as a variable from our protocol to be able to use it in some function in class:

    var delegate: ModelDelegate?

and then you have to conform this protocol to your viewController which will force you to use its subs, meaning that you will have to add its function to your viewController:

class ViewController:ModelDelegate {

var videos = [Video]() 
  override func viewDidLoad() {        
      super.viewDidLoad()            
      model.delegate = self	
      }        
    func videosFetched(_ videos: [Video]) {        
      self.videos = videos        
      videosTableView.reloadData()            
    }
}

Here we use our delegate and conform from our protocol to be able to fetch the video in our viewController, if you have any issue in this you can check the article related to this project from here.


5- Optionals

Optional is a great feature produced by swift to avoid the nil values for the variables and you can discover it by seeing a question mark ( ? ) which means that this variable is optional like we did before while declaring the name of the video:

var optionalVideo = Video()
print(optionalVideo.name)

so here we defined a variable called name from String and identify it as an optional by using the (?) mark and the default value for name is nil which means that this variable is empty by default, that’s why we were facing a warning while trying to print name before giving it a value and it will print nil.

The warning

what should we do to avoid these warnings? There are many ways to avoid this, let’s figure them out:

if optionalVideo.name == nil {    
    print("Sorry, the video has no name")
}
else {    
    print("optional video name is \(optionalVideo.name)")
}

Output: Sorry, the video has no name

The previous code shows how we can avoid the nil value but still we have another warning in the print statement which is:

Warning

This warning means that we need to provide a default value for the name to avoid any errors in the future, especially if we have any variable dependent on this name.

if optionalVideo.name == nil {    
   print("Sorry, the video has no name")
}
else {    
   print("optional video name is \(optionalVideo.name!)")
}

Output: Sorry, the video has no name

The only difference here is that we added ! at the end of optionalVideo.name which silenced the warning, and this (!) mark means that I’m sure that there is a value for the variable name because if the variable is not equal to nil you’re 100% sure that the variable has a value.

guard optionalVideo.name != nil else {            
         print("This video has no name")            
         return        
      }        
      print("video name is \(optionalVideo.name!)")

The guard statement here is used to check our variable, and if the variable has a value it will skip the else statement and go through the last print statement line.

We didn’t assign a value to it so the output will be:

Output: This video has no name

Another solution to do it is by setting a value for the variable:

optionalVideo.name = "Bleach ep 200"
if optionalVideo.name == nil {    
     print("Sorry, the video has no name")
}
else {    
    print("optional video's name is \(optionalVideo.name!)")
}

Output: optional video’s name is Bleach ep 200

Here we put our (!) mark as we are sure that the video already has a value since we already initialized it before.

The last solution is to use the if let statement “Optional Binding”:

if let videoName = optionalVideo.name {    
    print("optional video's name is \(videoName)")
}
else {    
    print("Sorry, the video has no name")
}

Output: optional video’s name is Bleach ep 200

We have put our variable in a constant and used this constant in our conditions.

We don’t need to put any marks ( ? ) or ! as we already put it into another constant.

Guess what !! Finally, the article is done and you are now aware of each point in Classes, Structs, Protocols, Functions, Closures & Optionals.

Further Reads and Resources can be found on the Official Swift Documentation.

Waiting for your Comments and Feedback.

Happy Coding.