Syncing UILabel with UITextField - ios

I am trying to sync two different UILabels with the value from two UITextFields, and if there is no data in the text field, then I would like them to keep their label placeholders that I set in the attributes inspector ("Label 1" & "Label 2"):
func textFieldDidEndEditing(_ textField: UITextField) {
labelOne.text = labelOneTextField.text
labelTwo.text = labelTwoTextField.text
}
However, when I finish entering text into the first text field and hit Done, the 2nd label becomes blank. So I tried this:
func textFieldDidEndEditing(_ textField: UITextField) {
if self.labelOneTextField != nil {
labelOne.text = "Label 1"
labelTwo.text = "Label 2"
} else {
labelOne.text = labelOneTextField.text
labelTwo.text = labelTwoTextField.text
}
}
However, this only sets a rule for if the first text field is blank, and it seems very messy. What is a better way to format this, especially considering that there will be many more text fields/labels in this form. Thank you.

Just get the value and check it's not empty:
if let labelOneText = labelOneTextField.text, !labelOneText.characters.isEmpty {
labelOne.text = labelOneText
}
if let labelTwoText = labelTwoTextField.text, !labelTwoText.characters.isEmpty {
labelTwo.text = labelTwoText
}

Select over the textfields:
switch textField {
case labelOneTextField:
labelOne.text = labelOneTextField.text
case labelTwoTextField:
labelTwo.text = labelTwoTextField.text
....
default:
break
}

Related

How to hide TEXT in TextField while clicking outside of TextField in Swift?

4(Swift4)
I am trying to hide the TextField's text after I end editing the TextField , I tried doing this :
textField.isHidden = true
But it's job is to hide the TextField , what I want to do is that hide TEXT of the textField after Tapping outside the textField..
EDIT : I want to hide it, I don't want asterisk , I want the text to be invisible and when I click on textField again it should appear the written text again
I tried this :
textField.text.isHidden = true
It gives me error if I do this way.
Your time and help will be highly appreciated!
Thank You!
You need to pack the text inside another variable
textContent = textField.text
textField.text = ""
if you want to hide the content like password set
textField.isSecureTextEntry = true
//
var textContent = ""
func textFieldDidEndEditing(_ textField: UITextField) {
textContent = textField.text!
textField.text = ""
}
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.text = textContent
}
Take textfield text into a variable and make textfield empty.
var textFieldText = textfield.text
textField.text = ""

How to go back when the UITextfield is empty in Swift code?

My question is: When the UITextField is empty, how do I click the "Backspace" button to go to the previous UITextField? I have been struggling trying to do this in my code below?
Second Question: How do I only allow 1 character to get entered in the UITextField?
I am new at Swift code and trying to learn. Any help would be great.
What I am trying to do is have the user be able to type in a code in the 6 UITextFields and be able to click the "Backspace" button on any one of the UITextFields with only allowing the user to enter one number in each UITextField.
Code Below:
#objc func textFieldDidChange(textfield: UITextField) {
let text = textfield.text!
if text.utf16.count == 0 {
switch textfield {
case textField2:
textField1.becomeFirstResponder()
textField1.backgroundColor = UIColor.blue
textField1.tintColor = .clear
case textField3:
textField2.becomeFirstResponder()
textField2.backgroundColor = UIColor.blue
textField2.tintColor = .clear
case textField4:
textField3.becomeFirstResponder()
textField3.backgroundColor = UIColor.blue
textField3.tintColor = .clear
case textField5:
textField4.becomeFirstResponder()
textField4.backgroundColor = UIColor.blue
textField4.tintColor = .clear
case textField6:
textField5.becomeFirstResponder()
textField5.backgroundColor = UIColor.blue
textField5.tintColor = .clear
textField6.resignFirstResponder()
textField6.backgroundColor = UIColor.blue
textField6.tintColor = .clear
default:
break
}
}
else if text.utf16.count == 1 {
switch textfield {
case textField1:
textField1.backgroundColor = UIColor.black
textField1.textColor = .white
textField1.tintColor = .clear
textField2.becomeFirstResponder()
textField2.backgroundColor = UIColor.black
textField2.textColor = .white
textField2.tintColor = .clear
case textField2:
textField3.becomeFirstResponder()
textField3.backgroundColor = UIColor.black
textField3.textColor = .white
textField3.tintColor = .clear
case textField3:
textField4.becomeFirstResponder()
textField4.backgroundColor = UIColor.black
textField4.textColor = .white
textField4.tintColor = .clear
case textField4:
textField5.becomeFirstResponder()
textField5.backgroundColor = UIColor.black
textField5.textColor = .white
textField5.tintColor = .clear
case textField5:
textField6.becomeFirstResponder()
textField6.backgroundColor = UIColor.black
textField6.textColor = .white
textField6.tintColor = .clear
case textField6:
textField6.resignFirstResponder()
default:
break
}
}
}
I'd just like to point out that I'm still relatively new to iOS and Swift in general, but even with just a few minutes of searching, I was able to find some seeds of ideas which provided me with the suggested solution.
Based on your (improved) question, I believe a different approach is required. What you really don't want to use a text component. "Why"?
I here you ask. Because they don't actually provide you with the functionality that you want and come with a considerable overhead.
For this, what you really want is more control. You want to know when a key is pressed and you want to respond to it (I know, sounds like a text component, but) and be notified when more extended functionality occurs, like the delete key is pressed.
After a few minutes of research, some trial and error, I found that the UIKeyInput is more along the lines of what you want.
It will tell you when text is inserted and, more importantly, will tell you when Delete is pressed
The added benefit is, you can filter the input directly. You can take the first character from the String and ignore the rest or auto fill the following elements with the remaining text. You can perform validation (for numerical only content) and what ever else you might want to do
So, I started a really new project, added a UILabel to the UIViewController in the storyboard, bound it to the source and implemented the UIKeyInput protocol as such...
class ViewController: UIViewController {
override var canBecomeFirstResponder: Bool {
return true
}
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
becomeFirstResponder()
}
}
extension ViewController: UIKeyInput {
var hasText: Bool {
return true
}
func insertText(_ text: String) {
print(text)
label.text = text
}
func deleteBackward() {
print("Delete backward")
}
}
I ran the project and when a key was typed, the label was updated with the new key and when delete was pressed, the Delete backward text was printed to console.
Now. You have some choices to make. To use a single UIViewController and (maybe) a series of UILabels and manage interactions within it, so when a key is typed, you present the next label as the input focus (and when delete is pressed, you move back) or do you create a series of UIControls which represent each digit and manage via some delegate call back process.
You may also need to implement the UITextInputTraits protocol, which will allow you to control the keyboard presented
You might also like to have a read through Responding to Keyboard Events on iOS, CustomTextInputView.swift and Showing the iOS keyboard without a text input which were just some of the resources I used to hobble this basic example together with.
you can use this extension for your second question:
import UIKit
private var maxLengths = [UITextField: Int]()
extension UITextField {
#IBInspectable var maxLength: Int {
get {
guard let length = maxLengths[self] else {
return Int.max
}
return length
}
set {
maxLengths[self] = newValue
addTarget(
self,
action: #selector(limitLength),
for: UIControlEvents.editingChanged
)
}
}
#objc func limitLength(textField: UITextField) {
guard let prospectiveText = textField.text,
prospectiveText.count > maxLength
else {
return
}
let selection = selectedTextRange
let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)
text = prospectiveText.substring(to: maxCharIndex)
selectedTextRange = selection
}
}
when you add this extension to your project you can see an extra attribute in "Attribute Inspector" tab and you can set the max length of UITextField.

How do I display multiple textfields to my labels?

I'm not sure if how I worded the question makes much sense so let me summarize.
I have 2 UITexfields and 2 UILabels.
I have it all working properly in terms of when I type into my first textField and hit return it will display my text.
Now I'm not sure how to get the same to apply to my other TextField and Label. I read that if I apply a tag to my textfield in Xcode "1" that I can apply tag "2" to my other textfield.
Here is the code I am using so when I press return it'll display textfield tag "1".
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField.tag == 1 {
nameDisplay?.text = textField.text!
}
return true
}
So to completely round this out, I want to display both separate textfields on each separate label.
Simply add an else to your if.
if textField.tag == 1 {
nameDisplay.text = textField.text
} else {
otherLabel.text = textField.text
}
Please note you do not need the ? or ! in that code.
Another option, if you have outlets for your text fields, is to do the following instead of bothering with tags:
if textField == someTextFieldOutlet {
nameDisplay.text = textField.text
} else {
otherLabel.text = textField.text
}
where someTextFieldOutlet is obviously needs to be the actual name of the appropriate text field outlet you have.

Cursor at the start of UITextField

A ViewController consist of two TextFields named textName & textEmail. View Controller loads with cursor on textName. textName contain pre populated word "#gmail.com".
On hitting keyboard's return Key from textName, focus is moved to Textfield textEmail. Here by default, cursor is placed after the word "#gmail.com"
I would like to get the cursor placed at the start. i.e. before #gmail.com
Here is my code. When i hit return key from textName, cursor goes to the beginning of textEmail. But when I tap on textEmail directly, cursor appears after the pre populated word. Please help me!
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == self.textName{
textEmail.becomeFirstResponder()
let desiredPosition = textEmail.beginningOfDocument
textEmail.selectedTextRange = textEmail.textRangeFromPosition(desiredPosition, toPosition: desiredPosition)
}
if textField == self.textEmail{
dismissViewControllerAnimated(true, completion: nil)
}
return true
}
As a note, I did try editing did begin action for textEmail and added below code but it didn't work either.
let desiredPosition = textEmail.beginningOfDocument
textEmail.selectedTextRange = textEmail.textRangeFromPosition(desiredPosition, toPosition: desiredPosition)
Try this instead:
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.textName{
let beginning = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: beginning, to: beginning)
}
}
So remove textEmail.becomeFirstResponder() and use textField.textRange instead of textEmail.textRangeFromPosition.
And inside of the textFieldDidBeginEditing function use the parameter textField as shown in my example above.
First tou set Delegate UITextFieldDelegate
After you TextField delegate set Self in viewDidLoad
Example
textName.delegate = self
textEmail.delegate = self
then Copy this method in your viewController
func textFieldShouldReturn(textField: UITextField) -> Bool
{
if textField == textName
{
textName.resignFirstResponder()
textEmail.becomeFirstResponder()
textEmail.text = "#gmail.com"
let newPosition = textField.beginningOfDocument
textEmail.selectedTextRange = textEmail.textRangeFromPosition(newPosition, toPosition: newPosition)
}
else if textField == textEmail
{
textEmail.resignFirstResponder()
}
return true
}

UITextField with user text + static mark

I have an UITextField which user sets its luggage weight as numbers in TextField. I want to set that textfields value with weight mark (for ex 10 KG which comes from user settings) so whatever user types, there will be KG mark at the end of its textfield. Is there any way for it?
do like
initially clear the value when begin start
func textFieldShouldBeginEditing(textField: UITextField) {
textField.text = ""
}
when editing is over append the kg
func textFieldDidEndEditing(textField: UITextField) {
yourTextfieldName.text = "\(textField.text!) KG"
}
Choice-2
func textFieldDidEndEditing(textField: UITextField)
{
if !textField.text!.rangeOfString("KG").location != NSNotFound {
self.textField.text = textField.text!.stringByAppendingString("KG")
}
}
You could place a "Label" next to the UITextField.
And then just change the text of the Label to whatever the user selects.
OR (but i dont know if that works), try to get the text form the textfield, add the unit (as a string) to the string from the textfield.

Resources