How to send email in Swift MFMailComposeViewController

Send Email In Swift 5.5 using MFMailComposeViewController

There might be a time when you have to ask the user to send an email directly to you or other users. Like recently while developing the CryptoWatch App, I wanted a way to let users report any bugs they find in the app and send it directly to me. For that, I searched and found the functionality to send email in swift using MFMailComposeViewController.

Using MFMailComposeViewController class, you can integrate send email in swift. MFMailComposeViewController class lets you assign the Recipient’s Email Address, Add People in CC, Add People in BCC, set the subject and body of the email and many other features.

If you are also interested in integrating push notifications in your app, you might wanna read this: How To Integrate Push Notifications In Swift

The mail will be sent only once the user has tapped the send email button. You can not send mail directly, user action is required.

Now let’s see how it can be implemented through code.

import UIKit
//1
import MessageUI

class ViewController : UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    //MARK: Setup
    //2
    func sendEmail() {
        if MFMailComposeViewController.canSendMail() {
            //3
            let mailVC = MFMailComposeViewController()
            mailVC.mailComposeDelegate = self
            //4
            mailVC.setToRecipients(["primary@gmail.com"])
            mailVC.setCcRecipients(["cc@gmail.com"])
            mailVC.setBccRecipients(["bcc@gmail.com"])
            
            mailVC.setSubject("Subject Goes Here")
            mailVC.setMessageBody("<p>Add body content here if required.</p>", isHTML: true)

            self.present(mailVC, animated: true)
        } else {
            // if mail functionality not available. canSendMail() fails in simulator.
            print("Unable to open mail. Please reach out to us at primary@gmail.com")
            Toast.show(message: "Unable to open mail. Please reach out to us at primary@gmail.com")
        }
    }
    
    //MARK: IBActions
    
    @IBAction func reportBtnPressed(_ sender : Any) {
        sendEmail()
    }

}

//MARK: Mail Delegate 

extension ViewController : MFMailComposeViewControllerDelegate {
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }
}
  1. We start by importing MessageUI for using MFMailComposeViewController.
  2. Create a sendEmail() function and check if user can send email or not. If it fails, handle the case in else statement. You should show an alert message to the user in this case to inform if about the alternate way to reach out.
  3. Create an object of the MFMailComposeViewController and set the delegate of the controller to self. You need mailComposeDelegate to access didFinishWith method to know that user has completed sending email and now you need to dismiss the mail controller. It does not dismisses itself automatically when the mail is sent, you will need to do it through the delegate method as we have done above.
  4. Set the receipient’s email address, cc, bcc, subject and message body. You dont need to set all these values, only use the ones you need.
  5. Once all set, present the controller.

NOTE: MFMailComposeViewController does not work in simulator. Use a real device to test it.

Now once you have implemented the send email functionality, this is how it should appear in your app:

A screenshot from the CryptoWatch app of MFMailComposeViewController

I hope you understood how to implement send email in swift using MFMailComposeViewController. If you have any queries, feel free to ask in the comments.

check if linked list is palindrome or not - swift

Swift – Check If Linked List is Palindrome or Not.

In this challenge, we will be checking whether a given linked list is palindrome or not.

For starters, you can copy the Linked List from the post Linked List in Swift if you don’t already have the Linked List created in your playground.

Once you have copied the code to the playground, let’s jump right into the question.

palindrome is a word, number, phrase, or other sequence of characters which reads the same backward as forward, such as madam or racecar

Wikipedia

To check for a linked list is palindrome or not, we need to check whether the linked list returns the same values when read from head to tail and tail to head.

While there may be other ways to do it, I came up with an idea to create a new linked list which is the reverse of the given linked list and then compare both the lists until list.value != newList.value

Let’s jump into the code and see how it works.

First let’s create a linked list and add data to it.

//1
var list = LinkedList<Int>()

//2
func addDataToList() {
    list.append(1)
    list.append(1)
    list.append(0)
    list.append(0)
    list.append(1)
    list.append(1)

}

addDataToList()

Now let’s write the function to check for palindrome.

func checkPalindrome<T : Equatable>(list : LinkedList<T>) -> Bool {
    //1
    var newList = LinkedList<T>()
    var current = list.head
    var isPalindrome = false
    //2 check if list not empty
    guard list.head != nil else {
        return false
    }

    //3 if only one element then it is a palindrome
    guard list.head?.next != nil else {
        return true
    }

    //4 if many elements

    while current != nil {
        newList.push(current!.value)
        current = current?.next
    }

    //5 check if equal

    var listIndex = list.head
    var newListIndex = newList.head

    while listIndex != nil {
        if listIndex?.value == newListIndex?.value {
            isPalindrome = true
        } else {
            return false
        }
        listIndex = listIndex?.next
        newListIndex = newListIndex?.next

    }
    //6
    print("OLD LIST:", list)
    print("NEW LIST:", newList)
    print("Palindrome: ", isPalindrome)


    return isPalindrome
}

Now let’s go to each point one by one.

  1. First we create a newList in which we will store the reverse of the linked list. We declare a variable current to store the position of linked list for traversing it. We also created a Bool variable that will store whether list is palindrome or not.
  2. Check if linked list is not empty. If it is, return nil.
  3. Check if linked list only contains one element. Return true as reverse of single node always would be the node itself.
  4. Now we traverse the linked list and append the nodes of the list to the new list. NOTE: The append function is a head-end insertion. It will traverse the list and append the elements of the list to the beginning of the newList. You can check the append function in the LinkedList.Swift to understand better.
  5. Now we traverse again through the list and this time we compare both the linked list by their current node values. If the values are same, keep traversing the list until the end. If the values are different, return from the function.
  6. Finally print the old and new list and whether the linked list is palindrome or not.
// OUTPUT

OLD LIST: 1 --> 1 --> 0 --> 0 --> 1 --> 1     
NEW LIST: 1 --> 1 --> 0 --> 0 --> 1 --> 1     
Palindrome:  true

You can see the output is true as the list reads the same from backward as well as forward. Hence it is a Palindrome.

There are many other ways to implement the same, if you come up with a better solution, let me know in the comments.

Print Reversed linked list

SWIFT – Print elements of Linked List in Reverse Order

Hey Folks! Today we will be doing a challenge to print out the elements of a linked list in reverse order in Swift

First of all, If you do not have a Linked List created in your playground, go to my Linked List In Swift blog post and copy the code.

Now let’s dive directly into the code.

First, we will create a linked list and append some data to it.

import Foundation

//1
var list = LinkedList<Int>()

//2
func addDataToList() {
    list.append(5)
    list.append(6)
    list.append(1)
    list.append(3)
    list.append(4)
    list.append(6)
}

addDataToList()

Approach 1

Now once we have added the data, let’s start writing our reverse function. Start writing down the code below the addDataToList()function call.

//1
// create a function that prints out the element of a linked list in reverse order

func reverseList<T>( _ list : LinkedList<T>) -> String {

    //2
    guard let _ = list.head else {
        return "Empty List"
    }
    
    //3
    var current = list.head
    var reverseString = ""
    
    //4
    repeat {
        reverseString =  "\(current!.value) " + reverseString
        current = current?.next
    } while (current != nil)
            
            
    return reverseString
}
print("BEFORE: ",list)
print("AFTER: ", reverseList(list))

Here is what we have done in the above code.

  1. We start the code by creating a generic function named reverseList that takes a linked list as a parameter and returns a string.
  2. With help of a guard statement, we check if the head node of the list is not empty. If it is nil, then the else block will be executed and will return Empty List.
  3. Once we have checked that the list is not empty, we declare two variables named current and reverseString. reverseString will hold the final reverse string and current will be used to traverse the list by incrementing its position after every loop.
  4. We are using a repeat-while loop which is swift equivalent to do while loop. In the repeat while loop, we are traversing through all the elements of the linked list. We add the current value to the beginning of the reverse string and then change the position of current to current?.next. We can also force unwrap the value of current in repeat-while loop as we know current will never be nil inside the block. The while loop will keep running until current is not equal to nil.

It’s time now to run the code and check if it’s working. Write a print statement to check if the function is working. Run the playground and you will see this output in the console.

BEFORE:  5 --> 6 --> 1 --> 3 --> 4 --> 6     
AFTER:  6 4 3 1 6 5 

Approach 2

In this approach, we will reverse the linked list and print it. If you are preparing for interviews, this approach would interest the interviewer more. Lets write down the code.

The trick to reverse a linked list is to just point next position of the node to previous. Example: 5->6->7->8->9->nil now instead of changing the position of the node., we will just change the arrows to point to previous nodes i.e. 5<-6<-7<-8<-9 and change the head to 9.

func reverse<T>(llist: Node<T>?) -> Node<T>? {
    //1 Write your code here
    
    // check for nil
    if llist == nil {
        return nil
    }
    
    //2 check if only element
    
    if llist?.next == nil {
        return llist
    }
    
    //3  check for multiple elements
    var head = llist
    var prev : Node<T>? = nil
    var current = llist
    var next = llist?.next
    
    //4
    while next != nil {
        current?.next = prev
        prev = current
        current = next
        next = current?.next
    }
    //5
    current?.next = prev
    head = current
    return head
}
//6
print("REVERSE: ", reverse(llist: list.head) as Any)

So let’s understand how the code above works.

  1. First we will check if the given linked list is not equal to list. If it equals to nil, return nil from the function.
  2. Next we check if the list only contains one node. If true, return the same as reverse of one node will be the same node itself.
  3. Now we check for multiple elements. Here we are declaring some variables to store the current, previous, next and head position. We have set the initial value of prev = nil as there is nothing previous to head.
  4. Now we will start a while loop till next is not equal to nil and keep increasing the position of next to its next node. We will swap values of current previous and next as shown in the code.
  5. The while loop only run till next != nil . That means the tail node which is currently assigned to current node is still not traveresed. We will assign the tail(current?.next = prev) index of its previous node and make the tail as head.
  6. Finally print the list.
//OUTPUT

LIST:  1 --> 2 --> 3 --> 4 --> 5 --> 6 --> 7      
REVERSE: 7 --> 6 --> 5 --> 4 --> 3 --> 2 --> 1  

Both the approaches above work perfectly. If you have any other issues, please reach out in the comments.

how to create linked list in swift

Linked List in Swift

A linked list is a collection of values arranged in a linear unidirectional sequence. Linked List in Swift can be implemented using the code shared in this blog post.

In this blog post, I am sharing the code that I wrote for creating a linked list. This is not a detailed blog post about what linked list, but just a reference code to create a linked list.

import Foundation

//MARK: Creating a Node

public class Node<Value> {
    public var value : Value
    public var next : Node?
    
    public init(value : Value, next : Node? = nil) {
        self.value = value
        self.next = next
    }
}

extension Node : CustomStringConvertible {
    public var description : String {
        guard let next = next else {
            return "\(value)"
        }
        return "\(value) --> " + String(describing: next) + " "
    }
}

//MARK: Creating a Linked List

public struct LinkedList<Value> {
    
    public var head : Node<Value>?
    public var tail : Node<Value>?
    
    public init() { }
    
    //MARK: Insert
    ///head-end insertion
    
    /*
     In swift, structs are immutable objects. by using mutating keyword in below function, the function will return a new struct in place. The mutating keyword lets the caller know that this method is going to make the value change.
     */
    
    public mutating func push(_ value : Value) {
        head = Node(value: value, next: head)
        if tail == nil {
            tail = head
        }
    }
    
    ///tail-end insertion
    
    public mutating func append(_ value : Value) {
        
        guard !isEmpty else {
            push(value)
            return
        }
        
        tail!.next = Node(value: value, next: nil)
        tail = tail!.next
    }
    
    ///insert-after
    
    public mutating func insert(value : Value, after node: Node<Value>) {
       
        guard tail !== head else {
            self.append(value)
            return
        }
        
        node.next = Node(value: value, next: node.next)
        
        
    }
    
    //MARK: Delete
    ///delete first
    @discardableResult
    public mutating func pop() -> Value? {
        defer {
            head = head?.next
            if isEmpty {
                tail = nil
            }
        }
        return head?.value
    }
    
    /// delete last
    
    @discardableResult
    public mutating func removeLast() -> Value? {
        // check if list is not empty.
        guard let head = head else {
            return nil
        }
        // if list contains only one element
        guard head.next != nil else {
            return pop()
        }
        var prev = head
        var current = head
        
        while let next = current.next {
            prev = current
            current = next
        }
        prev.next = nil
        tail = prev
        return current.value
        
    }
    
    ///delete at index
    
    public mutating func remove(after node : Node<Value>) -> Value? {
        // check if head next is tale
        defer {
            if node.next === tail {
                tail = node
            }
            node.next = node.next?.next
        }
        return node.next?.value
    }
    
    /// get node at index
    public func node(at index : Int) -> Node<Value>? {
        var currentNode = head
        var currentIndex = 0
        
        while currentNode != nil && currentIndex < index {
            currentNode = currentNode!.next
            currentIndex = currentIndex + 1
        }
        
        return currentNode
    }

}

extension LinkedList : CustomStringConvertible {
    public var description: String {
        guard let head = head else {
            return "Empty Linked List"
        }
        return String(describing: head)
    }
}

extension LinkedList : Collection {
  
    public var isEmpty : Bool {
        return head == nil
    }
    
    //MARK: Comparable
    public struct Index : Comparable {
   
        
        public var node : Node<Value>?
        
        static public func ==(lhs: Index , rhs: Index) -> Bool {
            switch (lhs.node,rhs.node) {
            case let (left? , right?):
                return left.next === right.next
            case (nil,nil):
                return true
            default:
                return false
            }
        }
        
        static public func <(lhs: Index , rhs: Index) -> Bool {
            guard lhs != rhs else {
                return false
            }
            let nodes = sequence(first: lhs.node) { $0?.next }
            return nodes.contains { $0 === rhs.node }
        }
        
    }
    
    //MARK: Collection and Sequence Protocol
    
    public func index(after i: Index) -> Index {
        return Index(node: i.node?.next)
    }
    
    public subscript(position: Index) -> Value {
        return position.node!.value
    }
    
    
    public var startIndex: Index {
        return Index(node: head)
    }
    
    public var endIndex: Index {
        return Index(node: tail)
    }
}
static and class keyword in swift

Static and Class Keyword in Swift

Before we talk about how static and class keyword are different with each other, lets see how they are similar.

How They Are Similar?

Static and Class keyword when applied on a variable or function, make it Type method.

Type Methods are the methods which you can call directly without creating instance of the class. Whereas, in Instance Method, we need to create an instance of the class first to access the property. Below is an example which will help you understand better.

class Employee  {
    
    var name = "Keshu"
    class var id : Int {
        return 007
    }
}

print(Employee.id) // Type Method : Accessing id directly on type. Without creating instance.
print(Employee().name) // Instance Method : Creating Instance then accessing name

Difference: Static and Class

STATICCLASS
Can be applied to Stored Property as well as Computed Properties.Can only be applied to Computed Properties.
Static method declaration are allowed in Struct as well as Classes.Class keyword can only be used in Classes.
NOTE: Static properties can not be overridden by inheriting classes.NOTE: Class properties can be overridden by inheriting classes.

static keyword is same like final class. final keyword makes the variable or function final i.e. they can not be overridden by any inheriting class.

class Employee  {
    
    static var name = "Keshu"
    class var id : Int {
        return 007
    }
}

class EmployeeAddress : Employee {
    
    override static var name = "Keshu New Name" // Error : Cannot override with a stored property 'name'
    
    override class var id: Int { // Runs successfully.
        return 100
    }
}

As you can see in above code, the static property can not be overridden by EmployeeAddress class. Whereas the id property has successfully been overridden. This is the major difference between Static and Class Keyword. I hope its clear to you now. If any queries, feel free to ask in comments.

Also, do you know what are Variadic Functions? Variadic Functions in Swift

Variadic functions in swift

Variadic Functions in Swift

Variadic Functions are those which accept from zero to N number of parameters.

The most common function which you use almost daily is the print() method

You can do print(“abc”) or you can also do print(“a”,”b”,”c”,”d”) or any number of parameters and it will print it all.

Let’s see how you can create your own variadic function.

func addition(_ numbers : Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum = sum + number
    }
    return sum
}


let sum = addition(0,1,2,3,4,5,6,7,8,9)
print(sum) // 45

You can see in the above code instead of just saying Int, I have entered Int… i.e. Int with three dots. This is how variadic functions are declared. Now, numbers will be an array of Int type and you may use for loop to sum the numbers. Or you can also reduce it to the below code:

func addition(_ numbers : Int...) -> Int {
    return numbers.reduce(0, +)
}

let sum = addition(0,1,2,3,4,5,6,7,8,9)
print(sum) // 45

That’s It. You now know how to create Variadic Functions in Swift. Cheers.

Extensions In Swift - how to use them?

Extensions In Swift

It’s been a long time since I have written a blog. But today, a post on Stackoverflow motivated me so much to write a post on the use of Extensions In Swift. Why? Because I have seen many beginners totally neglecting extensions and have no idea how useful they can be.

So I will try to list the points here today and discuss it one by one what functionalities do Extensions provide us:

  1. You may use Extensions for conforming to a protocol.
  2. Define instance methods and type methods
  3. Provide New Initializers.
  4. Define Subscripts
  5. Define and use new nested types.
  6. Add computed instance properties and computed type properties

NOTE:

Extensions can add new functionalities to a type, But they can not override an existing property.

Now let’s discuss the above points one by one.

Extension For Conforming to A Protocol

When using a UITableView, we always make our ViewController conform to UITableViewDataSource And UITableViewDelegate protocol methods.

class YouViewController : UIViewController, UITableViewDataSource, UITableViewDelegate { 
    // your viewController setup code
    // your table view callback methods
}

And if you are using let’s say, UICollectionView also in the same controller, your class declaration will look something like this now:

class YouViewController : UIViewController, UITableViewDataSource, UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    // your viewController setup code
    // your table view callback methods
    // your collection view callback methods
}

Do you see what’s happening above? The more and more functionalities you are adding, your class has to conform to the protocols and then you will have to write all the callback methods in the same class which make the code hard to read. What’s the solution? Glad you asked. Extensions.

class YourViewController : UIViewController { 
    // your viewController setup code
}

extension YourViewController : UITableViewDataSource, UITableViewDelegate { 
    // your table view callback methods
}

extension YourViewController : UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 
    // your collection view callback methods
}

This way you can make your code easy to read using Extensions In Swift. If you were not following this pattern till now, I would suggest better start following it.

Extensions on Instance Method or Type Methods

Instance Method is the method which you call on an instance of a type.

For eg: The code below declares a class named ArithmeticOperations and then declares a function inside it named add(), which takes multiple Integers as input and then returns the sum of all the Integers.

NOTE: I have used Variadic Parameters in defining the add function, If you don’t know about it, read this post and learn within a minute. Variadic Parameters in Swift

import Foundation

class ArithmeticOperations : NSObject {
    
    // Instance Method
    func add(_ num : Int...) -> Int { // variadic parameter
        return num.reduce(0, +) // adds all the numbers in num array and returns the sum.
    }
    
    // Type Method
    class func printAnything() {
        print("Aabara ka dabara")
    }
}

//creating instance and then calling the method
let sumObj = ArithmeticOperations()
print(sumObj.add(0,1,2,3,4,5,6,7,8,9)) // 45


// calling the type method

ArithmeticOperations.printAnything() // Aabara ka dabara

As you can see above, the instance method can only be called by creating an instance of it first and then calling the function.

Whereas, for calling the type method, we can directly do it without creating an instance.

Now that you have understood what instance method and type method is, let’s come back to how we can use Extensions in it.

class ArithmeticOperations : NSObject {
    func add(_ num : Int...) -> Int {
        return num.reduce(0, +)
    }
    class func printAnything() {
        print("Aabara ka dabara")
    }
}

//MARK: Subtraction
extension ArithmeticOperations {
    func subtract(_ num : Int...) -> Int {
         return num.reduce(0, -)
    }
}

let subtractObj = ArithmeticOperations()
print(subtractObj.subtract(10,9,8,7,6,5,4,3,2,1)) // -55

In the above code, we have created an extension for the same class ArithmeticOperations for and added a Subtraction function in it. And now we can use the subtraction method same as the addition method anywhere in the project.

Extensions come really handy when you have to work on pre-defined methods.

Let’s say you want to extend the Int type and add a function to it which returns the cube of a number.

extension Int {
    func cube() -> Int {
        return self*self*self
    }
}
print(3.cube()) // 27

Easy right?

Add New Initializers Using Extension

Extensions can add new initializers to existing types. This enables you to extend other types to accept your own custom types as initializer parameters, or to provide additional initialization options that were not included as part of the type’s original implementation.

Extensions can add new convenience initializers to a class, but they can’t add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation.

Apple

Below is an example of how you can create your own initializer in extensions.

extension UIColor {
    convenience init<T: BinaryInteger>(r: T, g: T, b: T, a: T = 255) {
        self.init(red: .init(r)/255, green: .init(g)/255, blue: .init(b)/255, alpha: .init(a)/255)
    }
    convenience init<T: BinaryFloatingPoint>(r: T, g: T, b: T, a: T = 1.0) {
        self.init(red: .init(r), green: .init(g), blue: .init(b), alpha: .init(a))
    }
}

let green1 = UIColor(r: 0, g: 255, b: 0, a: 255)  // r 0,0 g 1,0 b 0,0 a 1,0
let green2 = UIColor(r: 0, g: 1.0, b: 0, a: 1.0)  // r 0,0 g 1,0 b 0,0 a 1,0

let red1 = UIColor(r: 255, g: 0, b: 0)  // r 1,0 g 0,0 b 0,0 a 1,0
let red2 = UIColor(r: 1.0, g: 0, b: 0)  // r 1,0 g 0,0 b 0,0 a 1,0

Other than the above, you can also use extensions for Subscripts, Nested Types and Computed Properties

To learn more about it you can follow the official Swift Doc link here: Declaring Subscript, Nested Types and Computed Properties in Extensions in Swift

If any queries, let me know in the comments. Thanks for reading.

Push Notifications in iOS

Show Push Notifications when app running in the foreground iOS Swift

Push notifications are a nice way to inform your users about the offers, user-specific updates or any message that you want to broadcast to all users.

If your app is running, it can be in two states. Either in the background or in the foreground.

Push notifications work well when the app is in the background and you can see the notification banner presented with a sound(if provided) on your iPhone/iPad. But what about when the app is in the foreground?

Apple does not show up push notifications by default when your app is in the foreground state. So what to do? You have to write some code to deal with the situation of your app receiving a notification while it is in the foreground.

If you receive local or remote notifications while your app is running in the foreground, you’re responsible for passing the information to your users in an app-specific way.

Apple

Apple guidelines are clear. You are responsible for handling the push notifications in the foreground state. So how to achieve this? Don’t worry, it’s pretty easy. Below are the steps.

Steps to show Push Notifications in the foreground

Step 1 : Add delegate UNUserNotificationCenterDelegate in AppDelegate class.

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

Step 2: Set the UNUserNotificationCenter delegate in didFinishLaunchingWithOptions

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        UNUserNotificationCenter.current().delegate = self
        return true
    }

Step 3: This step will allow your app to show Push Notification even when your app is in the foreground

  
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo
        print(userInfo) // the payload that is attached to the push notification
        // you can customize the notification presentation options. Below code will show notification banner as well as play a sound. If you want to add a badge too, add .badge in the array.
        completionHandler([.alert,.sound])
    }

Step 4: If you want to perform an action with the click of a push notification, you can do it using the below method

   
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                   didReceive response: UNNotificationResponse,
                                   withCompletionHandler completionHandler: @escaping () -> Void) {
           let userInfo = response.notification.request.content.userInfo
           // Print full message.
           print("tap on on forground app",userInfo)
           completionHandler()
       }
    

Well, that was it! You have successfully configured push notifications to receive them in the foreground state too.

It was EASY, right? Do let me know in the comments.

Also, do not forget to become a subscriber by entering your email below so that you can receive the tutorials directly in your inbox.

Namaste!

passing data between view controllers

Passing Data Between View Controllers in Swift

Passing data from one view controller to another view controller is something you need in almost every app. But yet I have seen many people struggling with this. So I have decided to write this blog for beginner level iOS App Developers to understand how to pass the data.

There could be two scenarios when you are changing the view controllers.

  1. You are moving from ViewController1 to ViewController2
  2. You are coming back from ViewController2 to ViewController1

Also, there could be two ways in which you are moving from ViewController1 to ViewController2.

  1. Using the navigation controller
  2. Using storyboard segues.

Now, we will discuss passing data between the view controllers using the navigation controller and using storyboard segues separately.

Passing data when pushing or presenting View Controller

1. Sending data from ViewController1 to ViewController2

For navigating from VC1 to VC2, we use the “push” method. For coming back from VC2 to VC1, we use the “pop” method. We can also use “present” if we want to present our view controller modally.

Below is the code to move from VC1 to VC2

//1 Instantiating ViewController2 from storyboard
let vc2 = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ViewController2") as! ViewController2

//2 pushing ViewController2 to move to top of the navigation stack
self.navigationController?.pushViewController(vc2, animated: true) 

The above code would take you from VC1 to VC2. But where are we passing data? Relax.

//1  
let vc2 = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ViewController2") as! ViewController

//2
vc2.myName = self.userName
        
//3
self.navigationController?.pushViewController(vc2, animated: true)

So in the above code, you can see #2, here we are assigning self.userName, which is in ViewController1 to vc2.myName. When the View Controller 2 will load, its myName value will be equal to the value of self.userName that we passed.

Easy, Right? similarly, you may also do when presenting your view controller modally.

//1  
let vc2 = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ViewController2") as! ViewController

//2
vc2.myName = self.userName
        
//3
self.present(vc2, animated: true, completion: nil)

You can pass any data type, whether string, array, JSON, etc.

Sending data back from ViewController2 to ViewController1

Sending data forward is easy. While sending data back to the controller can be a bit tricky for beginners.

Data is sent back to the controller with the help of Delegates.

Delegates are a design pattern that allows one object to send messages to another object when a specific event happens.

James Rochabrun

I am writing a separate blog on sending data back to View Controller using Delegates. I will update the link here.

Passing Data using Segues

Segues are another way of transition from one view controller to others and are implemented through a storyboard. I will not cover how to create a segue here as I assume you already know it. If not, here is the link from Apple Documentation

The starting point of a segue must be a view or object with a defined action, such as a control, bar button item, or gesture recognizer. You can also create segues from cell-based views such as tables and collection views.

Apple Docs

Segues can be implemented in two ways:

  1. From a view or object to Next View Controller
  2. From View Controller to Next View Controller

When you do not need to pass any data, you can create an object to the Next View Controller segue and implemented it all through a storyboard.

But when you need to pass the data, we need to make sure to create the segue between View Controller to View Controller. There can be multiple segues between view controllers and we use segue identifiers to identify them.

Go ahead and create a segue from ViewController1 to ViewController2 and click on the connecting arrow line to open it in Attribute Inspector in the right panel. Here, assign the identifier to the segue. For example: nextVCSegue

Also, create a button in your ViewController1 on click of which we will perform the segue. Declare an @IBAction of that button.

//1 
 @IBAction func submitBtnPressed(_ sender : Any) {
    //2
    performSegue(withIdentifier: "nextVCSegue", sender: self)
 }
  
 //3 prepareForSegue function is called everytime you perform a segue.

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        //4
        if segue.identifier == "nextVCSegue" {
            //5
            if let nextVC = segue.destination as? ViewController2 {
                //6
                nextVC.myName = self.name
            } else {
                print("error")
            }
        }
    }
  1. We created an @IBAction that will execute on the submit button click.
  2. Here we are telling the controller to perform segue using the identifier nextVCSegue.
  3. Now when performSegue starts, it will call prepareForSegue function. In this function, we will assign the data that we need to pass to the next view controller.
  4. PrepareForSegue function is called for every segue that is happening from the view controller. But here in our case, we only want to pass the data when the segue is from ViewController1 to ViewController2. And how would we identify it? Yes. Using segue Identifier. So we will check if the segue identifier is nextVCSegue or not.
  5. segue has a destination property that you can use to know what your destination view controller is. So here we are assigning out nextVC object to the destination view controller which is ViewController2.
  6. Now we can use nextVC to access all the properties you declared in ViewController2 and assign its value here. So here we are assigning our name variable value to nextVC myName variable.

Done. You have successfully passed your data from ViewController1 to ViewController2.

Subscribe below to receive latest blog updates directly in your inbox and help yourself become a better developer.