Use callback to binding with another object

What is Callback?

Callback is a function that must be performed after completing another function.

It is used in the form of closure and uses asynchronous programming to communicate, but care must be taken as it can affect memory.

When to use?

The callback is used in request functions of an API, as an error or success response, and also as a form of connection between two classes. Which is good for the MVVM architecture, and can replace in some situations Observers and delegates.

Let's go to practice

We are getting to build an app, during which it'll signal when text fields aren't empty, having instant feedback once you can submit or not.

Open xcode and make a project, the name of my project are going to be called callback-mvvm.

Build the storyboard (two labels, two textfields, and a button)

Screen Shot 2021-02-13 at 15 31 43

Go to View Controller to attach the texfields, make the Outlets:

Screen Shot 2021-02-13 at 11 14 50

Pay attention to the action: we'll use the Editing Changed option because when the word is typed, it'll be checked whether the text box is going to be empty or not.

Screen Shot 2021-02-13 at 11 16 20

will appear as if this:

Screen Shot 2021-02-13 at 11 20 22

Now! Let's do a touch MVVM pattern, during which the ViewController cannot have any logic, just present. Let's create a file called: CallBack, which might be our ViewModel, during which our ViewController will communicate.

After creating the file, we'll create a class, CallBackViewModel, which can have two attributes of type String and one among type function.


class CallBackViewModel{

    var txtName:String = ""

    var txtPassword:String = ""

    var updateBtnSubmit: ((Bool) -> ())?

}

What's it going to be for:

The txtName and txtPassword will serve as the textfield checker for the ViewController, whatever word you type, we will check if the box is empty or not. And the function attribute is used to talk, through a callback with the ViewController. We will send the information: true or false if the textfields are empty or not.

let's return to the ViewController and instantiate our CallBackViewModel class.

import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var tfName: UITextField!

    @IBOutlet weak var tfPassword: UITextField!

    @IBOutlet weak var btnSubmit: UIButton!

    let callBack = CallBackViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func actionTfName(_ sender: UITextField) {
    }


    @IBAction func actionTfPassword(_ sender: UITextField) {
    }

}

After we instantiate, we'll send each letter that we type within the text field to the CallBackViewModel class, using the variables we created within the CallBackViewModel to verify.

Screen Shot 2021-02-13 at 11 38 51


    @IBAction func actionTfName(_ sender: UITextField) {
        self.callBack.txtName = sender.text!
        //or
        //self.callBack.txtName = tfName.text!

    }

    @IBAction func actionTfPassword(_ sender: UITextField) {
        self.callBack.txtPassword = sender.text!
        //or
        //self.callBack.txtName = tfPassword.text!
    }

However, to see each letter, we must create a property observer within the string variables, Let's do a didSet, and in them, we'll create a function to see if the variable is empty or not.

Screen Shot 2021-02-13 at 11 53 07


import Foundation


class CallBackViewModel{

    var txtName:String = "" {
        didSet{
            verifier()
        }
    }
    var txtPassword:String = ""{
        didSet{
            verifier()
        }
    }

    var updateBtnSubmit: ((Bool) -> ())?

    func verifier(){

    }
}

In the verifier function, we'll validate our attributes, if both attributes aren't empty, we'll attend our updaterBtnSubtmit function true, otherwise false.

Screen Shot 2021-02-13 at 11 55 47

func verifier(){
    updateBtnSubmit?(!(txtName.isEmpty) && !(txtPassword.isEmpty) ? true:false)
}

We finished the logic of our application!

Let's return to the ViewController, to indicate when the button is enabled or not. But first, we'd like to disable the button, because we only want to activate it when both textfields are filled.

Screen Shot 2021-02-13 at 13 03 06

@IBOutlet weak var btnSubmit: UIButton!{
    didSet{
        self.btnSubmit.isEnabled = false
    }
}

In viewdidLoad, we'll create a function to call our callback. Let's call updateButton

override func viewDidLoad() {
    super.viewDidLoad()

    updateButton()

}

func updateButton(){


}

In the updateButton function, we'll call the function variable of the CallBackViewModel class, as I said at the start of the tutorial, the callback is represented by a closure, so like our variable, updateBtnSubmit, it's a function that's within the CallBackViewModel class. Let's do a closure:

func updateButton(){
    callBack.updateBtnSubmit = { [weak self] bool in
        self!.btnSubmit.isEnabled = bool
    }

}

This closure will always be receiving a bool. Because the CallBackViewModel class has the function of checking textfields.

In the end, our ViewController goes like this:



import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var tfName: UITextField!

    @IBOutlet weak var tfPassword: UITextField!

    @IBOutlet weak var btnSubmit: UIButton!{
        didSet{
            self.btnSubmit.isEnabled = false
        }
    }

    let callBack = CallBackViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()

        updateButton()

    }

    @IBAction func actionTfName(_ sender: UITextField) {
        self.callBack.txtName = sender.text!
        //or
        //self.callBack.txtName = tfName.text!

    }

    @IBAction func actionTfPassword(_ sender: UITextField) {
        self.callBack.txtPassword = sender.text!
        //or
        //self.callBack.txtName = tfPassword.text!
    }

    func updateButton(){
        callBack.updateBtnSubmit = { [weak self] bool in
            self!.btnSubmit.isEnabled = bool
        }

    }



}

and our CallBackViewModel class:


import Foundation


class CallBackViewModel{

    var txtName:String = "" {
        didSet{
            verifier()
        }
    }
    var txtPassword:String = ""{
        didSet{
            verifier()
        }
    }

    var updateBtnSubmit: ((Bool) -> ())?

    func verifier(){
        updateBtnSubmit?(!(txtName.isEmpty) && !(txtPassword.isEmpty) ? true:false)
    }
}

Result:

Kapture 2021-02-13 at 13 15 13

GitHub