Sum of 3 Uitextfield

Sum of three textfield value without clicking a button (Swift - Xcode)

One way is to add self as the target to the text fields, for the control event .editingChanged

impact.addTarget(self, action: #selector(textChanged), for: .editingChanged)
// do the same for other textfields

Then declare a textChanged method. This should handle what happens when the texts in the text fields change. One implementation would be to add up all the values in the text fields (if any, and is valid) and display it in the label.

func textChanged() {
let impactValue = Int(impact.text!)
let rigourValue = Int(rigour.text!)
let responseValue = Int(response.text!)
total.text = String(describing:
(impactValue ?? 0) + (rigourValue ?? 0) + (responseValue ?? 0)
)
}

Optionally, you can conform to UITextFieldDelegate:

class TryingoutController: UIViewController, UITextFieldDelegate {

}

and implement shouldChange according to this answer by Thuggish Nuggets. Then, set the delegates of the text fields to self:

impact.delegate = self
// do the same for other text fields.

Sum of multiple UITextfields without a button action

First set delegate self to your textfield

- (void)viewDidLoad 
{
[super viewDidLoad];
[firstTextField setDelegate:self];
[secondTextField setDelegate:self];
[thirdTextField setDelegate:self];
}

Calculate your total in following method.

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
total.text = [NSString stringWithFormat:@"d",([firstTextField.text intValue])+([secondTextField.text intValue])+([thirdTextField.text intValue])];
return YES;
}

Sum up every digit in UITextField in Swift

Let's say you have following date string in your text field.

var dateString = "19/09/2018"

let sum = dateString.reduce(0) { (res, char) -> Int in
var res = res
if let number = Int(String(char)) {
res+=number
}
return res
}

print(sum) ==> 30

And using segue method you can just pass this sum to your next VC.

func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { }

best way to calculate the result of a multiple uitextfields

You can make good use of the nil coalescing operator ?? to handle the cases where your textfields are empty or don't contain legal values:

let value1 = Int(textfield1.text ?? "") ?? 0
let value2 = Int(textfield2.text ?? "") ?? 0
let value3 = Int(textfield3.text ?? "") ?? 0
let value4 = Int(textfield4.text ?? "") ?? 0
let sum = value1 + value2 + value3 + value4

Or for a functional approach, collect the textfields in an array literal and use flatMap and reduce to convert the values and produce the sum:

let values = [textfield1, textfield2, textfield3, textfield4].flatMap({$0.text}).flatMap({Int($0)})
let sum = values.reduce(0, +)

what's the easiest way to add the value of two text fields to equal a sum to a label

You can use the power of functional swift like this:

if let textField1String = textField1.text, let textField2String = textField2.text {
let arr = [textField1String, textField2String]
let result = arr.compactMap({ Int($0) }).reduce(0, +) //Cast in Int value + using reduce to sum all the values of array
speedLabel.text = "\(result)"
}

Set the maximum character length of a UITextField

While the UITextField class has no max length property, it's relatively simple to get this functionality by setting the text field's delegate and implementing the following delegate method:

Objective-C

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Prevent crashing undo bug – see note below.
if(range.length + range.location > textField.text.length)
{
return NO;
}

NSUInteger newLength = [textField.text length] + [string length] - range.length;
return newLength <= 25;
}

Swift

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

let currentCharacterCount = textField.text?.count ?? 0
if range.length + range.location > currentCharacterCount {
return false
}
let newLength = currentCharacterCount + string.count - range.length
return newLength <= 25
}

Before the text field changes, the UITextField asks the delegate if the specified text should be changed. The text field has not changed at this point, so we grab it's current length and the string length we're inserting (either through pasting copied text or typing a single character using the keyboard), minus the range length. If this value is too long (more than 25 characters in this example), return NO to prohibit the change.

When typing in a single character at the end of a text field, the range.location will be the current field's length, and range.length will be 0 because we're not replacing/deleting anything. Inserting into the middle of a text field just means a different range.location, and pasting multiple characters just means string has more than one character in it.

Deleting single characters or cutting multiple characters is specified by a range with a non-zero length, and an empty string. Replacement is just a range deletion with a non-empty string.

A note on the crashing "undo" bug

As is mentioned in the comments, there is a bug with UITextField that can lead to a crash.

If you paste in to the field, but the paste is prevented by your validation implementation, the paste operation is still recorded in the application's undo buffer. If you then fire an undo (by shaking the device and confirming an Undo), the UITextField will attempt to replace the string it thinks it pasted in to itself with an empty string. This will crash because it never actually pasted the string in to itself. It will try to replace a part of the string that doesn't exist.

Fortunately you can protect the UITextField from killing itself like this. You just need to ensure that the range it proposes to replace does exist within its current string. This is what the initial sanity check above does.

swift 3.0 with copy and paste working fine.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
let str = (textView.text + text)
if str.characters.count <= 10 {
return true
}
textView.text = str.substring(to: str.index(str.startIndex, offsetBy: 10))
return false
}

Hope it's helpful to you.

How to set up UITextFieldDelegate for multiple text fields?

If your goal is to have all three text fields follow the same rule, set the delegate for all three. The shouldChangeCharactersIn only needs to check the “current” text field into which the user is currently typing.

A minor observation, but I also would avoid recreating the CharacterSet of allowed characters repeatedly. You can simply make that a property.

That reduces it down to something like:

private let allowedCharacters = CharacterSet(charactersIn: "ABCDEFGĞHIİJKLMNOÖPRSŞTUÜVYZ")

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if (textField.text?.count ?? 0) - range.length + string.count > 1 {
return false
}

return allowedCharacters.isSuperset(of: CharacterSet(charactersIn: string.localizedUppercase))
}

If you want them only entering uppercase characters, I would:

  • Change the keyboard capitalization to “All Characters”, so they are more likely to not enter lowercase letters:

    Sample Image

  • Optionally change the capitalization by adding an “editing changed” action for your text field to:

    @IBAction func editingChanged(_ textField: UITextField) {
    textField.text = textField.text?.localizedUppercase
    }

    You might have to experiment whether you want to use localizedUppercase or uppercased() or uppercased(with:).

    Note, this “uppercase the whole string” logic is a little sloppy. If you were allowing multi-character strings in your input, you really would want to capture where the cursor was and restore it. (Otherwise it could be an annoying UX where if the user is changing the first character of a multi-character string, the cursor would jump to the end.) E.g., a simple rendition might be:

    @IBAction func editingChanged(_ textField: UITextField) {
    let range = textField.selectedTextRange
    textField.text = textField.text?.localizedUppercase
    textField.selectedTextRange = range
    }

    But for your single character input, the simpler example, above, should be sufficient.



Related Topics



Leave a reply



Submit