Custom TextField change settings at the time of creation - ios

I want all of TextField to have small letters.and if I need to change to a larger one I could write inside the creation.But my code doesn't work, what am I doing wrong?
class ViewController: UIViewController
private let TextField: CustomTextField = { //LETTERS (no work)
let textfield = CustomTextField()
textfield.autocapitalizationType = .allCharacters
return textfield
}()
private let TextField2: CustomTextField = { //letters (work)
let textfield = CustomTextField()
return textfield
}()
class CustomTextField: UITextField
override func layoutSubviews() {
super.layoutSubviews()
self.autocapitalizationType = .none
}

layoutSubviews() function is called after the initialization of your textFields. If you debug your code, you will see that TextField.autocapitalizationType will be set to .allCharacters. But after initialization of your object, layoutSubviews() will be called and autocapitalizationType will be set to .none. So you need to define the self.autocapitalizationType = .none inside init of your CustomTextField.

First, remove the override of layoutSubviews() - as mentioned by Muhammed's answer, setting the autocapitalizationType here will overwrite your custom value as soon as layoutSubviews() is called.
Then, if you give your CustomTextField a custom initializer with a parameter for the capitalization type like this:
init(autocapitalizationType: UITextAutocapitalizationType = .none) {
super.init(frame: .zero)
self.autocapitalizationType = autocapitalizationType
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Then you can just initialize it all in one step like this, no closure required:
private let textField = CustomTextField(autocapitalizationType: .allCharacters)
If you don't want to set a type then you can leave the CustomTextField() parentheses empty since the initializer adds .none as a default.

Related

By setting text to UIButton resets button font to default

In my code, I have created a custom button (i.e subclass of UIButton), But I am unable to set the font to the button. Have observed that, If I am using self.titleLabel?.text = title it works fine but whenever I am using method self.setTitle(title, for: .normal) font get reset to system font. I need that font for all the states of the button so I have to use the function setTitle. My custom button code is as follows
class RoundedButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
styleButton()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
styleButton()
}
func styleButton(title: String = "button", font: UIFont = .customFont16) {
self.setTitle(title, for: .normal)
self.backgroundColor = UIColor.yellow
titleLabel?.font = font
}
}
You can add a variable for setting font in a custom class. Then set the font from the viewController.
var titleFont: UIFont = UIFont.preferredFont(forTextStyle: .footnote) {
didSet {
titleLabel?.font = titleFont
}
}
Add the above code into your custom class and access it in the viewController like this.
#IBOutlet weak var roundButton: RoundedButton!
override func viewDidLoad() {
super.viewDidLoad()
roundButton.titleFont = .caption1
}

Calling delegate methods in custom UITextField class

So this might be basic Swift knowledge but I'm struggling to find this info anywhere online. I'm trying to create a custom text field glass with global styles that utilizes UITextFieldDelegate methods. In particular I'm trying to use the function textFieldDidBeginEditing(). In my example below I'm just trying to print "hello" when a text field is being edited, however nothing is being printed to the console when I begin typing in my custom text field.
If I'm doing anything incorrectly please let me know, as I don't work with Swift too much. Thank you!
class LoFMTextField: UITextField {
override init(frame: CGRect) {
super.init(frame: frame)
styleTextField()
}
required init?(coder LoFMDecoder: NSCoder) {
super.init(coder: LoFMDecoder)
styleTextField()
}
func styleTextField() {
layer.cornerRadius = 5.0
layer.borderWidth = 1.0
layer.borderColor = UIColor.white.cgColor
backgroundColor = UIColor.white
}
}
extension UITextFieldDelegate {
func textFieldDidBeginEditing(textField: UITextField!) {
print("hello")
}
}
Add this line inside styleTextField
self.delegate = self
Then
extension LoFMTextField : UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
print("hello")
}
}
Note: it's (_ textField: UITextField) not (textField: UITextField!)

Can I chain delegates together?

Swift 4.0 iOS 11.x
I have created a simple text field class, that uses the UITextFieldDelegate. I wanted to add to it an additional protocol that I could use to pass on the fact that the text entry to said field completed. A Delegate chain, since once I have picked up the fact that text entry has exited in the custom class I cannot pass it down to the VC in which the UITextField class is within it seems.
import UIKit
protocol ExitedFieldDelegate {
func exited(info: String)
}
class IDText: UITextField, UITextFieldDelegate {
internal var zeus: ExitedFieldDelegate? = nil
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
delegate = self
}
required override init(frame: CGRect) {
super.init(frame: frame)
delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.textColor = UIColor.black
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {
if (delegate != nil) {
let info = self.text
zeus?.exited(info: info!)
}
}
}
I added this code to the viewController I wanted to use my custom class within.
class ConfigViewController: UIViewController, ExitedFieldDelegate
And of course the method required by the protocol
func exited(info: String) {
print("The brain has left the room")
}
And I made it a delegate of said protocol so I got this in effect
var blah = IDText()
blah.delegate = self
But well it doesn't work. Am I attempting the impossible here, should I simply use default notifications instead? or indeed something else?
By setting:
blah.delegate = self
You are overwriting setting the delegate to self in the initializers.
What you want is to rewrite:
internal var zeus: ExitedFieldDelegate? = nil
to:
weak var zeus: ExitedFieldDelegate?
To be able to use weak (you want that to prevent retain cycle), update protocol definition to:
protocol ExitedFieldDelegate: class {
func exited(info: String)
}
And then change this:
var blah = IDText()
blah.delegate = self
to:
var blah = IDText()
// you want to set zeus instead of the delegate field
blah.zeus = self

iOS - UIButton become first responder to open keyboard

I need to open keyboard on button click for UIButton (not using/for UITextField). I have tried to create custom button by overriding variable canBecomeFirstResponder but it's not working.
Is there any other way to do so?
Note: I want to set UIPIckerView as an input view of UIButton in key board frame.
Here is my code.
class RespondingButton: UIButton {
override var canBecomeFirstResponder: Bool {
return true
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
// common init
}
}
In my view controller, I connected button action.
class TestViewController: UIViewController {
#IBAction func testBecomeFirstResponder(button: RespondingButton){
button.becomeFirstResponder() // Not working.
}
}
Here is what I would do.
Create transparent textField 1x1px, lets say it is myTextField.
Then add your desired button. In the button action make the myTextField.becomeFirstResponder().
Create view:
let pvBackground: UIView = {
let v = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
v.backgroundColor = .white
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
In viewDidLoad:
pvBackground.addSubview(yourPickerView)//add the picker into the pvBackground
myTextField.inputView = pvBackground
I added the pickerView into the another view to be able to customize it more.
Add conformance to UIKeyInput like this. It should work.
class RespondingButton: UIButton, UIKeyInput {
override var canBecomeFirstResponder: Bool {
return true
}
var hasText: Bool = true
func insertText(_ text: String) {}
func deleteBackward() {}
}

iOS: How do I make my UITextfield highlight when tapped?

Do I have to do this with code or is there something in the inspector that I'm missing?
Unlike UIButton, a UITextField does not have a highlighted state. If you want to change the color of the textfield when it receives focus, you can use the UITextFieldDelegate's - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
This will be called when the control first receives focus. From there you can change the background and/or text color. Once focus leaves the control, you can use - (BOOL)textFieldShouldEndEditing:(UITextField *)textField to reset the colors.
In Swift 2, you can use the delegate functions like below,
class CustomTextField: UITextField, UITextFieldDelegate{
init(){
super.init(frame: CGRectMake(0, 0, 0, 0))
self.delegate = self // SETTING DELEGATE TO SELF
}
func textFieldDidBeginEditing(textField: UITextField) {
textField.backgroundColor = UIColor.greenColor() // setting a highlight color
}
func textFieldDidEndEditing(textField: UITextField) {
textField.backgroundColor = UIColor.whiteColor() // setting a default color
}
}
If you still want to be able to use other delegate functions in you ViewController, I recommend you to add this:
override weak var delegate: UITextFieldDelegate? {
didSet {
if delegate?.isKindOfClass(YourTextField) == false {
// Checks so YourTextField (self) doesn't set the textFieldDelegate when assigning self.delegate = self
textFieldDelegate = delegate
delegate = self
}
}
}
// This delegate will actually be your public delegate to the view controller which will be called in your overwritten functions
private weak var textFieldDelegate: UITextFieldDelegate?
class YourTextField: UITextField, UITextFieldDelegate {
init(){
super.init(frame: CGRectZero)
self.delegate = self
}
func textFieldDidBeginEditing(textField: UITextField) {
textField.backgroundColor = UIColor.blackColor()
textFieldDelegate?.textFieldDidBeginEditing?(textField)
}
func textFieldDidEndEditing(textField: UITextField) {
textField.backgroundColor = UIColor.whiteColor()
textFieldDelegate?.textFieldDidBeginEditing?(textField)
}
}
This way your view controller doesn't need to know that you have overwritted the delegate and you can implement UITextFieldDelegate functions in your view controller.
let yourTextField = YourTextField()
yourTextField.delegate = self

Resources