skip to Main Content

I have a beginner question about protocols and functions in Swift. I’ve been following along with Angela Yu’s course for about a month.

I’m trying to wrap my head around how in the code below, the function "textFieldShouldReturn" can be activated without being called.

import UIKit

class WeatherViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var conditionImageView: UIImageView!
    @IBOutlet weak var temperatureLabel: UILabel!
    @IBOutlet weak var cityLabel: UILabel!
    
    @IBOutlet weak var searchTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        searchTextField.delegate = self
       
    }

    
    @IBAction func searchPressed(_ sender: UIButton) {
        print (searchTextField.text!)
        searchTextField.endEditing(true)
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        print (searchTextField.text!)
        searchTextField.endEditing(true)
        return true
    }

I understand that because the WeatherViewController is connected to the protocol UITextFieldDelegate, I am able to access functions such as func textFieldShouldReturn or func textFieldShouldEndEditing. But I’m struggling to visualise what’s happening behind the scenes, that makes it possible for the functions to activate when I run the program even though my code does not explicitly calls it.

If someone can explain like I’m 5, that would be greatly appreciated.

3

Answers


  1. The function can be activated without being called

    This is the wrong sentence here. The correct one is:

    The function called without ME calling it!

    Imagine this (although it’s just a concept):

    1. Someone codes a UIButton as the return button of the keyboard.
    2. In the touchUpInside event of that button calls this:
    
    if self.delegate?.textFieldShouldReturn?(self) ?? true {
        // Insert new line or smt.
    }
    
    1. if the delegate is not nil and the textFieldShouldReturn is implemented in your code, your code will be called. Otherwise, a default implementation will be executed instead.

    Note that it is just a concept and it is not the real implementation of the UITextField class

    Login or Signup to reply.
  2. UITextFieldDelegate is a protocol. When you have inherited your controller with this Protocol it means now all the functions(calls of this Protocol, in our case TEXTFIELD) can be received in the controller.

    In viewDidLoad, you have told your specific textfield(in our case it is "searchTextField") to give you all the calls of textfield in this controller.

    Login or Signup to reply.
  3. The tl;dr answer is that, when your view loads, your WeatherViewController sets itself as the delegate of searchTextField and it is searchTextField that is calling your function.

    You are probably aware that everything you see in the user interface of your app is implemented as a Swift object[*]. In the case of searchTextField the object is an instance of UITextField. This object is responsible for everything to do with the search text field on the screen. It draws the text field and its contents and it manages all the input. So, if you press a key when the field has focus, it is the UITextField that accepts the input, updates the content and tells the windowing system that it needs to be redrawn. In the case of the return key being pressed, the UITextField will have some default action, which, I think is to surrender focus and let the windowing system move to the next field.

    The delegate is an object that UITextField uses to allow you to modify the default behaviour at various points. A delegate implements a collection of functions that are called at various points in the life cycle of the UITextField. So, recognising that you might not want the default behaviour when the return key is pressed, the UITextField

    • checks if it has a delegate
    • if it does have a delegate, checks if the delegate has the function textFieldShouldReturn
    • if the delegate does have the function, the UITextField calls it.

    You can do pretty much anything you like in the delegated function, within certain limits and then the UITextField checks the return value to see if it should also do the default action.

    I have a couple of notes on terminology:

    • WeatherViewController is not connected to the protocol. We say it adopts the protocol or it conforms to the protocol. The protocol sets constraints for classes and structs that adopt it. Usually the methods listed in a protocol must be implemented in the class that adopts it. This is not the case with UITextFieldDelegate – the methods are all marked as optional – but it does place the constraint that your class must be an Objective-C class. Optional methods don’t exist for pure Swift classes. In your case, UIViewController is an Objective-C class and you inherit from it, so the constraint is satisfied.
    • we don’t activate functions, we call them. Your question should really be "how is my function called when it is not referenced in my code?"

    Sorry to be a bit picky about the language, but I find it really helps to get things straight in my head if I adopt the correct terminology.

    [*] Objective-C object actually

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search