Where to put protocol UITextFieldDelegate:NSObject? pg 151

#1

Beginning programmer here. I’m having problems with where to place the block of code for “protocol UITextFieldDelegate: NSObjectProtocol {…}”. Does it go in a separate file? The ebook doesn’t say where to place that code.

If I place the block of code within "class ConversionViewController: UIViewController, UITextFieldDelegate {…}"
It won’t build - I get error: Declaration is only valid at file scope

The same is true if I place the protocol block outside the class.
It won’t build - I get error: ‘optional’ can only be applied to members of an @objc protocol

Any and all help is greatly appreciated.

#2

Do it like this:

//
//  ViewController.swift
//
//  TextFieldProtocol jam...
//
import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - UITextFieldDelegate methods

    func textFieldDidBeginEditing (textField: UITextField) {
        print ("textFieldDidBeginEditing:...")
    }
    
    func textFieldDidEndEditing (textField: UITextField) {
        print ("textFieldDidEndEditing: \(textField.text)")
    }
    
    func textFieldShouldReturn (textField: UITextField) -> Bool {
        print ("textFieldShouldReturn:...")
        textField.resignFirstResponder()
        return true
    }
}

[quote]It won’t build - I get error: ‘optional’ can only be applied to members of an @objc protocol
[/quote]
That is because optional can only appear inside a protocol declaration.

[Become a competent programmer faster than you can imagine: pretty-function.org]

#3

Thanks Ibex10 - but I’m sorry - I’m not following your solution. Or maybe I’m just not getting the idea behind the block of code for the UITextFieldDelegate protocol.

The problem I’m having (starting on page 151) is with the UITextFieldDelegate protocol. Does it even go in the code at all? I’m confused.
Specifically, I’m not sure where to put this block of code:

 protocol UITextFieldDelegate: NSObjectProtocol {
    
    optional func textFieldShouldBeginEditing(textField: UITextField) -> Bool
    optional func textFieldDidBeginEditing(textField: UITextField)
    optional func textFieldShouldEndEditing(textField: UITextField) -> Bool
    optional func textFieldDidEndEditing(textField: UITextField)
    optional func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
        replacmentString string: String) -> Bool
    optional func textFieldShouldClear(textField: UITextField) -> Bool
    optional func textFieldShouldReturn(textField: UITextField) -> Bool
 }

///////////////////////////////////
Below is my code for the project:
As mentioned previously…
If I place the block of code within "class ConversionViewController: UIViewController, UITextFieldDelegate {…}"
It won’t build - I get error: Declaration is only valid at file scope

The same is true if I place the protocol block outside the class.
It won’t build - I get error: ‘optional’ can only be applied to members of an @objc protocol

//
//  ConversionViewController.swift
//  WorldTrotter

import Foundation
import UIKit

class ConversionViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var celsiusLabel: UILabel!
    @IBOutlet var textField: UITextField!
    
    var fahrenheitValue: Double? {
        didSet {
            updateCelsiusLable()
        }
    }

    
    var celsiusValue: Double? {
        if let value = fahrenheitValue {
            return (value - 32) * (5/9)
        }
        
        else {
            
        return nil
        }
    }
    
    func updateCelsiusLable() {
        if let value = celsiusValue {
            celsiusLabel.text = numberFormatter.stringFromNumber(value)
        }
        else {
            celsiusLabel.text = "???"
        }
    }
    
    @IBAction func fahrenheitFieldEditingChanged(textField: UITextField) {

        if let text = textField.text, value = Double(text){
            fahrenheitValue = value
        }
        else {
            fahrenheitValue = nil
        }
    }
        
    let numberFormatter: NSNumberFormatter = {
        let nf = NSNumberFormatter()
        nf.numberStyle = .DecimalStyle
        nf.minimumFractionDigits = 0
        nf.maximumFractionDigits = 1
        return nf
    }()
    
    
    @IBAction func dismissKeyboard(sender: AnyObject) {
        textField.resignFirstResponder()
    }
       
    func textField(textField: UITextField,
        shouldChangeCharactersInRange range: NSRange,
        replacmentString string: String) -> Bool {
            
            print ("Current text: \(textField.text)")
            print ("Replacment text: \(string)")
            
            return true
    }
    
}

Thanks much for your help!

#4

It does not. If you want to declare that a class conforms to a protocol, just pretend that the class inherits from the protocol name. How do you indicate that a class inherits from another class?

Next, when a class conforms to a protocol the class must implement, i.e. define, the functions listed in the protocol. The block of code you have is a list of the function names that need to be defined inside a class that conforms to the protocol. The catch is that some functions in a protocol can be optional, which means that a class that conforms to the protocol doesn’t have to define an optional function if it doesn’t want to. How do you define a function inside a class?

You can read more about protocols in Apple’s Swift programming guide here:

developer.apple.com/library/ios … CH25-ID267

Unfortunately, iOS programming is an advanced topic in computer programming. At some point, if you feel completely overwhelmed and you aren’t learning anything, then consider ordering a beginning Python book and getting started with computer programming that way. After a couple of years of Python (including exploring GUI programming in Python and creating iPhone apps with the Kivy library), you will be much better prepared to tackle iOS programming–although it will still be challenging.

#5

Learn to understand what that block of code is intended to say.

It says this:

  1. UITextFieldDelegate is a protocol;
  2. As such, it declares a set of methods;
  3. Methods marked as optional are not required to be implemented by the adopter of the protocol.

A protocol is used used to specify behaviour by declaring a set of methods. If a class is to implement this behaviour, it adopts the protocol and implements at least all the required methods.

Protocols are good for naming a set of methods; thus, they make it easier to refer to those methods collectively, and also to check that a class conforms to a protocol (that is, it implements the methods in that protocol.)

For example:

// All dogs can bark and some can bite
protocol DogBehaviour {
   func bark ()
   optional func bite ()
}

// Adopt DogBehaviour protocol
class HarmlessDog : DogBehaviour
{
   func bark () {...}
}

// Adopt DogBehaviour protocol
class DangerousDog : DogBehaviour
{
   func bark () {...}
   func bite () {...}
}

let HD = HarmlessDog ()
HD.bark ()

let DD = DangerousDog ()
DD.bark ()
DD.bite ()

If all this still sounds jibber jabber, heed 7stud7stud’s advice.

#6

I know this topic is old but this applies to anyone using Swift 3

The answer is to define the protocol before the class and add @objc in front of the protocol declaration.

@objc protocol UITextFieldDelegate {
    @objc optional func textFieldShouldBeginEditing(textField: UITextField) -> Bool
    @objc optional func textFieldDidBeginEditing(textField: UITextField)
    @objc optional func textFieldShouldEndEditing(textField: UITextField) -> Bool
    @objc optional func textFieldDidEndEditing(textField: UITextField)
    @objc optional func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange,
                        replacmentString string: String) -> Bool
    @objc optional func textFieldShouldClear(textField: UITextField) -> Bool
    @objc optional func textFieldShouldReturn(textField: UITextField) -> Bool
}

Docs say you only need @objc in front of the declaration but Xcode wanted it before each optional func too.