14

So i have these textfields that i realised that they all have same properties, so i created new class called "UserInputs" and extended from UITextField, everything works properly except one thing, UITextFieldDelegate functions doesn't work, i mean when i focus on them it doesn't work, i want to add it in code because when you focus on my input fields they change border, how do i properly subclass from UITextField

the only problems that i have are that functions:

textFieldDidBeginEditing
textFieldDidEndEditing

and so doesn't work.

this is my class where everything happens:

import Foundation

import UIKit

class RegistrationViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var firstName: UserInputs!
@IBOutlet weak var test: UserInputs!

override func viewDidLoad() {
    super.viewDidLoad()
    self.firstName.delegate = self
    self.test.delegate = self
}

}

This is my subclass:

class UserInputs: UITextField{

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)!
    createBorder()
}
func createBorder(){
    let border = CALayer()
    let width = CGFloat(2.0)
    border.borderColor = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).CGColor
    border.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: self.frame.size.height)
    border.borderWidth = width
    self.layer.addSublayer(border)
    self.layer.masksToBounds = true
    //print("border created")
}
func textFieldDidBeginEditing() {
    print("focused")
    self.pulseBorderColor()
}
func textFieldDidEndEditing() {
    print("lost focus")
    self.reversePulseBorderColor()
}
func pulseBorderColor(){
    let pulseAnimation = CABasicAnimation(keyPath: "borderColor")
    pulseAnimation.duration = 0.35
    pulseAnimation.fromValue = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).CGColor
    pulseAnimation.toValue = UIColor(red: 252/255, green: 180/255, blue: 29/255, alpha: 1.0).CGColor
    pulseAnimation.fillMode = kCAFillModeForwards
    pulseAnimation.removedOnCompletion = false
    pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    self.layer.sublayers![0].addAnimation(pulseAnimation,forKey: nil)
    }
func reversePulseBorderColor(){
    let pulseAnimation = CABasicAnimation(keyPath: "borderColor")
    pulseAnimation.duration = 0.35
    pulseAnimation.fromValue = UIColor(red: 252/255, green: 180/255, blue: 29/255, alpha: 1.0).CGColor
    pulseAnimation.toValue = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).CGColor
    pulseAnimation.fillMode = kCAFillModeForwards
    pulseAnimation.removedOnCompletion = false
    pulseAnimation.timingFunction = CAMediaTimingFunction(name:  kCAMediaTimingFunctionEaseInEaseOut)
    self.layer.sublayers![0].addAnimation(pulseAnimation,forKey: nil)
    }
}

this code worked when i had no subclass and was doing it inside my main class, but after creating subclass focus functions stopped working, everything else works

main problem is that i want to implement

func textFieldDidBeginEditing() {
    print("focused")
}

func textFieldDidEndEditing() {
    print("lost focus")
}

these in my textfields so i don't write it over and over again

nikagar4
  • 830
  • 4
  • 11
  • 23

3 Answers3

17

It looks like the UITextFieldDelegate functions you have in your code are a little off. They should be:

func textFieldDidBeginEditing(textField: UITextField) {
    print("focused")
}
 func textFieldDidEndEditing(textField: UITextField) {
    print("lost focus")
}

And since you want the UserInputs objects to be their own delegates, I've added that code, too. To demonstrate this, I have the following two files:

ViewController.swift

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    var textField: UserInputs!

    override func viewDidLoad() {
        super.viewDidLoad()
        textField = UserInputs(frame: CGRectMake(100, 100, 200, 40))
        view.addSubview(textField!)
    }
}

UserInputs.swift

import UIKit

class UserInputs: UITextField, UITextFieldDelegate {

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        delegate = self
        createBorder()
    }
    required override init(frame: CGRect) {
        super.init(frame: frame)
        delegate = self
        createBorder()
    }
    func createBorder(){
        let border = CALayer()
        let width = CGFloat(2.0)
        border.borderColor = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).CGColor
        border.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: self.frame.size.height)
        border.borderWidth = width
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true
        //print("border created")
    }
    func textFieldDidBeginEditing(textField: UITextField) {
        print("focused")
    }
    func textFieldDidEndEditing(textField: UITextField) {
        print("lost focus")
    }
}
Jason Barker
  • 3,020
  • 1
  • 17
  • 11
  • 1
    maybe but it didn't solve the problem, when i write code there is no suggestion on: textFieldDid... but when i write it in main class it gives me suggestions – nikagar4 Jan 14 '16 at 06:49
  • 1
    These delegate methods belong in the delegate and not within the UserInputs class. – Jason Barker Jan 14 '16 at 06:50
  • it still doesn't work, i will post the main class so you can completely see what i'm doing – nikagar4 Jan 14 '16 at 06:55
  • I updated my answer with the code I have that's working. – Jason Barker Jan 14 '16 at 07:05
  • it kinda works but i've tried that already before, the problem is that, when i focus on textfields, i want them to use their own functions, something like this: textField.pulseBorderColor() and it doesn't work because textField is of type UITextField not UserInputs, i can't make it UserInputs because of the protocol – nikagar4 Jan 14 '16 at 07:12
  • Got it. I've adjusted the code to align with the information from your last comment. – Jason Barker Jan 14 '16 at 07:20
  • oh and by the way how can i add constraint from the code, since i create textfield using only code, i don't know how to add constraints, i'm new to swift and xcode – nikagar4 Jan 14 '16 at 07:28
  • Constraints require a bit of code. Have a look at this question and answer: http://stackoverflow.com/questions/26180822/swift-adding-constraints-programmatically – Jason Barker Jan 14 '16 at 07:36
  • 1
    Erm, this doesn't work for me. The delegates embedded within the UITextField class never get called. Has anyone had any success with this? – wuf810 Nov 02 '16 at 11:01
  • i have the same issue...did you fixed it? – Jaseel.Dev Oct 09 '19 at 10:49
17

Your UITextFieldDelegate should probably stay in your RegistrationViewController.

Instead of overriding the delegate you can do this. In your init method, add a target to self with the appropriate function.

class UserInputs: UITextField {
  override init(frame: CGRect) {
      super.init(frame: frame)
      self.addTarget(self, action: "formatText", for: .editingChanged)
  }

  required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      self.addTarget(self, action: "formatText", for: .editingChanged)
  }

  func formatText() {
     // Edit self.text here
  }
//.......//
}
Gaston Gonzalez
  • 427
  • 3
  • 6
  • That's what I was looking for. That way you don't block any view from implementing MVC in the future, Thanks! :) – arbel03 Feb 19 '17 at 19:32
  • This should be the accepted answer. It does what the OP wants, and it doesn't interfere with use of delegates. – Grimxn Jan 11 '18 at 17:41
0

You can change border by calling delegate in UserInput

class UserInputs: UITextField, UITextFieldDelegate{

    let border = CALayer()

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        createBorder()
        self.delegate = self

    }

    func createBorder(){
        let width = CGFloat(2.0)
        border.borderColor = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).CGColor
        border.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: self.frame.size.height)
        border.borderWidth = width
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true
        //print("border created")
    }

    func pulseBorderColor(){
        border.borderColor = UIColor.greenColor().CGColor
    }

    func normalColor(){
        border.borderColor = UIColor(red: 55/255, green: 78/255, blue: 95/255, alpha: 1.0).CGColor
    }

    func textFieldDidBeginEditing(textField: UITextField) {
        print("focused")
        pulseBorderColor()
    }

    func textFieldDidEndEditing(textField: UITextField) {
        print("lost focus")
        normalColor()
    }
}
Hamza Ansari
  • 3,009
  • 1
  • 23
  • 25