how to add 2 textfields togethers as int (swift3) - ios

I am trying to convert 2 textfields to ints and then add them together. I would also like to print the sum in the log.
let jake = t3.text! + t4.text!

Convert text into Int in Swift and an addition like we can do...
//set before this condition Validation for Text field
let sum = (Int(textFirst.text ?? "0")! + Int(textSecond.text ?? "0"))!
print(sum) //Output here
//MARK: - Text Field Delegate Method for Input validation
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
let allowedCharacters = CharacterSet.decimalDigits
let characterSet = CharacterSet(charactersIn: string)
return allowedCharacters.isSuperset(of: characterSet)
}

let t3Value: Int? = Int(t3.text!)
let t4Value: Int? = Int(t4.text!)
let final = t3Value! + t4Value!
print("Sum \(final)")
Hope this helps!

Try this:
if let val1 = Int(t3.text!), let val2 = Int(t4.text!)
{
let sum = val1 + val2
print(sum)
}

Related

Swift UITextfield Delegate Function "shouldChangeCharactersIn" - How can I stop editing for a second UITextfield?

I have a problem, I have two Textfields and want a max length of 20 Characters for both.
I use the following code but it only works for my first Textfield. What did I wrong? I hope someone can help me.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField === nameTextField {
let currentText = nameTextField.text
guard let stringRange = Range(range, in: currentText!) else {
return false
}
let updateText = currentText?.replacingCharacters(in: stringRange, with: string)
return updateText?.count ?? 0 < 20
} else if textField === numberTextField {
let currentText = numberTextField.text
guard let stringRange = Range(range, in: currentText!) else {
return false
}
let updateText = currentText?.replacingCharacters(in: stringRange, with: string)
return updateText?.count ?? 0 < 20
}
return true
}
You probably forgot to set the delegate for the second one.
Also no need for this complex logic! Just keep the first 20 like:
textView.text = String(textView.text.prefix(20))

How can I achieve this functionality to enter DOB in UITextField

I used a variable to store the text being entered and modifying it by appending the remaining suffix of "mm/dd/yyyy". I am getting the functionality, but if I try to update the cursor to the right position, its creating a problem.
I used the textfield.selectedTextRange to move the cursor from EOF to position I need. But, it is replacing the text entered with last "y" from "mm/dd/yyyy". So If I enter "12" the text changes from mm/dd/yyyy| to "yy|/mm/yyyy" instead of "12|/dd/yyy"
Am I doing it the wrong way?
let dobPlaceholderText = "mm/dd/yyyy"
var enteredDOBText = ""
#objc func textFieldDidChange(_ textField: UITextField){
enteredDOBText.append(textField.text.last ?? Character(""))
let modifiedText = enteredDOBText + dobPlaceholderText.suffix(dobPlaceholderText.count - enteredDOBText.count)
textField.text = modifiedText
setCursorPosition(input: dob.textField, position: enteredDOBText.count)
}
private func setCursorPosition(input: UITextField, position: Int){
let position = input.position(from: input.beginningOfDocument, offset: position)!
input.selectedTextRange = input.textRange(from: position, to: position)
}
The suggestion of matt and aheze in the comments to use textField(_:shouldChangeCharactersIn:replacementString:) is very promising in such use cases.
The procedure could look something like this:
determine the resulting text as it would look like after the user input and filter out all non-numeric characters
apply the pattern as defined in your dobPlaceholderText
set the result in the UIText field
determine and set new cursor position
In source code it could look like this:
let dobPlaceholderText = "mm/dd/yyyy"
let delims = "/"
let validInput = "0123456789"
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let filteredText = filtered(textField.text, range: range, replacement: string)
let newText = applyPattern(filteredText, pattern: Array(dobPlaceholderText))
textField.text = newText
let newPosition = newCursorPosition(range: range, replacement: string, newText: newText)
setCursorPosition(input: textField, position: newPosition)
return false
}
The actual implementation of the three methods filtered, applyPattern and newCursorPosition depends on the exact detail behavior you want to achieve. This is just a sample implementation, use something that reflects your requirements.
private func filtered(_ text: String?,range:NSRange, replacement: String) -> Array<Character> {
let textFieldText: NSString = (text ?? "") as NSString
let textAfterUpdate = textFieldText.replacingCharacters(in: range, with: replacement)
var filtered = Array(textAfterUpdate.filter(validInput.contains))
if filtered.count >= dobPlaceholderText.count {
filtered = Array(filtered[0..<dobPlaceholderText.count])
}
return filtered
}
private func applyPattern(_ filtered: Array<Character>, pattern: Array<Character>) -> String {
var result = pattern
var iter = filtered.makeIterator()
for i in 0..<pattern.count {
if delims.contains(pattern[i]) {
result[i] = pattern[i]
} else if let ch = iter.next() {
result[i] = ch
} else {
result[i] = pattern[i]
}
}
return String(result)
}
private func newCursorPosition(range: NSRange, replacement: String, newText: String) -> Int {
var newPos = 0
if replacement.isEmpty {
newPos = range.location
}
else {
newPos = min(range.location + range.length + 1, dobPlaceholderText.count)
if newPos < dobPlaceholderText.count && delims.contains(Array(newText)[newPos]) {
newPos += 1
}
}
return newPos
}
Demo

Swift 3: Append to UITextField while Editing Changed

Probably a simple one although no answers updated for Swift 3.
How can I append characters to a UITextField while the textfield is being edited? The characters should be appended while the user types not after the editing ends.
For example:
User types: 1
Field Updates: 1 kg
User types 123
Field Updates: 123 kg
Was trying to tackle this using EditingChanged IBActions but how can I stop the value from appending "kg" for each new character that is typed?
Example "1 kg 2 kg 3 kg"
Try this way it may help you out.
Add target for textfield on text is being editing
textField.addTarget(self, action: #selector(self.textFieldDidChange), for: .editingChanged)
In Observer method try the following way
func textFieldDidChange(textfield: UITextField) {
var text = textField.text?.replacingOccurrences(of: " KG", with: "")
text = text! + " KG"
textField.text = text
print("Text changed")
}
You want the UITextFieldDelegate method
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
I should warn you that this is incredibly irritating to implement because of the way Swift handles Strings. Its usually better to just cast the text to NSString (which is UTF16) and deal with the range that way. However if you are just doing numbers and can live with a fixed decimal place the case is much easier to handle. Keep a custom number that represents your "real number" and just update the field to reflect your formatted number. Since you only allow digits there are finitely many cases to handle (this code will not handle copy/paste).
You must set the textfield delegate and keyboard (to numeric) in the storyboard.
class ViewController: UIViewController{
#IBOutlet weak var textField: UITextField!
fileprivate let digits: Set<String> = ["0","1","2","3","4","5","6","7","8","9"]
fileprivate let decimalPlaces = 2
fileprivate let suffix = " kg"
fileprivate lazy var formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = self.decimalPlaces
formatter.maximumFractionDigits = self.decimalPlaces
formatter.locale = NSLocale.current
return formatter
}()
fileprivate var amount: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if digits.contains(string) {
amount *= 10
amount += Int(string)!
} else if string == "" {
amount /= 10
}
guard amount > 0 else {
textField.text = ""
return false
}
let digitsAfterDecimal = formatter.maximumFractionDigits
var value = Double(amount)
for _ in 0..<digitsAfterDecimal {
value /= 10
}
textField.text = formatter.string(from: NSNumber(value: value))! + suffix
return false
}
}
Conform the textfield delegate to the controller and try this solution.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == "" {
// handle backspace scenario here
return true
} else if var textString = textField.text {
let unitString = "kg"
if textString.contains(unitString) {
textString = textString.replacingOccurrences(of: unitString, with: "")
textString += string + unitString
textField.text = textString
} else {
textField.text = string + unitString
}
return false
}
return true
}
Use UITextFieldDelegate's function:
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool // return NO to not change text
You'll have to combine the text from the textfield.text and string parameter from this function using the range parameter to get the string To Be formed on textfield while you type/paste/clear based on range.
Keep track on range.length as it always gives the count of string being deleted/cleared and is 0 when you enter text. And range.location gives the position of edit.
Then you can set the formed string to textfield.text and return false Remember - return false and not true

Getting a error No '+' candidates produce the expected contextual result type 'NSString'

I am writing the code in swift 3 and Xcode 8.
Here is the code:
import Foundation
import UIKit
class CashTextFieldDelegate : NSObject, UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let oldText = textField.text! as NSString
var newText = oldText.replacingCharacters(in: range, with: string) as NSString
var newTextString = String(newText)
let digits = NSCharacterSet.decimalDigits
var digitText = ""
for c in newTextString.unicodeScalars {
if digits.contains(c) {
digitText.append(String(c))
}
}
// Format the new string
if let numOfPennies = Int(digitText) {
newText = "$" + self.dollarStringFromInt(numOfPennies)+ "." + self.centsStringFromInt(numOfPennies)
} else {
newText = "$0.00"
}
textField.text = newText as String
return false
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField.text!.isEmpty {
textField.text = "$0.00"
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true;
}
func dollarStringFromInt(value: Int) -> String {
return String(value / 100)
}
func centsStringFromInt(value: Int) -> String {
let cents = value % 100
var centsString = String(cents)
if cents < 10 {
centsString = "0" + centsString
}
return centsString
}
}
for this line of code from above :
newText = "$" + self.dollarStringFromInt(numOfPennies) + "." + self.centsStringFromInt(numOfPennies)
I get a error like this:
No '+' candidates produce the expected contextual result type 'NSString'.
Unable to resolve this error.
Any help with little explanation would be appreciated
Unlike Swift 2, NSString and String aren't automatically converted between each other.
Try something like this:
newText = ("$" + self.dollarStringFromInt(numOfPennies) + "." + self.centsStringFromInt(numOfPennies)) as NSString
You can further clean this up by using a consistent type-- either String or NSString throughout (e.g. changing function returns, etc).

How do I limit text lengths for different UITextFields in Swift?

I have an iOS Xcode 7.3 Swift2 project I'm working on. It has different UITextFields that are limited to 3 digits, specifically only numbers. They are assigned to the UITextFieldDelegate and it's working well.
Here is where I limit them:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
let limitLength = 3
if newLength > limitLength {
return false
}
let numberOnly = NSCharacterSet.init(charactersInString: "0123456789")
let stringFromTextField = NSCharacterSet.init(charactersInString: string)
let strValid = numberOnly.isSupersetOfSet(stringFromTextField)
return strValid
}
However, some of the UITextFields need to be limited to numbers still AND also limited to a single digit, how can I institute this in the section above, only for those specific UITextFields?
The names of the UITextFields that need to be single digits are:
widthInches
lengthInches
I tried placing this after the first guard section with no luck:
guard let text2 = widthInches.text else { return true }
let newLength2 = text2.characters.count + string.characters.count - range.length
let limitLength2 = 3
if newLength2 > limitLength2 {
return false
}
You can also try this code for limit textfield
actually i am using here textfield tag. Because custom textfield.
If you using custom textfield like TextfieldEffect in this condition tag will help you for limit of Textfield.
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool{
if textField.tag == txtCountryCode.tag{
let maxLength = 4
let currentString: NSString = textField.text!
let newString: NSString =
currentString.stringByReplacingCharactersInRange(range, withString: string)
return newString.length <= maxLength
}
if textField.tag == txtMobileNumber.tag{
let maxLength = 10
let currentString: NSString = textField.text!
let newString: NSString =
currentString.stringByReplacingCharactersInRange(range, withString: string)
return newString.length <= maxLength
}
return true
}
I hope this will help you.
The function shouldChangeCharactersInRange passes in the particular textField as one of its parameters. You can look at that and see if it points to the same instance as the ones you want to shorten, like this:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else { return true }
var limitLength = 3
if textField == widthInches || textField == lengthInches {
limitLength = 1
}
let newLength = text.characters.count + string.characters.count - range.length
if newLength > limitLength {
return false
}
let numberOnly = NSCharacterSet.init(charactersInString: "0123456789")
let stringFromTextField = NSCharacterSet.init(charactersInString: string)
let strValid = numberOnly.isSupersetOfSet(stringFromTextField)
return strValid
}
Assuming all other requirements are the same (numbers only) this will do the trick.
There are other ways, for example - you could subclass UITextField and add a limitLength field, then use that field in the delegate, but that's probably overkill for just 2 exceptions.
Hello in your func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool the textField param is the textField that has trigger this event so you can check with yours textfields objects and if are equal to one of them then make a different behavior
I hope this helps you,
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
return (textField.text?.utf16.count ?? 0) + string.utf16.count - range.length <= TEXT_FIELD_LIMIT
}
This counts the number of characters based on UTF-16 representation, as range.length is given in UTF-16 base. If you need to count the number of characters in other ways, the expression may get longer. If you want only numbers to be input use textField.keyboardType = UIKeyboardTypeDecimalPad . If you want specific textFields then add tags and compare them and if they are equal you can implement your specific code for that.
Check this link for detailed answer :
http://www.globalnerdy.com/2016/05/24/a-better-way-to-program-ios-text-fields-that-have-maximum-lengths-and-accept-or-reject-specific-characters/
update for swift 3 add this class and call it TextField.swift. it will add the limit input on the storyboard.
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
// Any text field with a set max length will call the limitLength
// method any time it's edited (i.e. when the user adds, removes,
// cuts, or pastes characters to/from the text field).
addTarget(
self,
action: #selector(limitLength),
for: UIControlEvents.editingChanged
)
}
}
func limitLength(textField: UITextField) {
guard let prospectiveText = textField.text,
prospectiveText.characters.count > maxLength else {
return
}
// If the change in the text field's contents will exceed its maximum
length,
// allow only the first [maxLength] characters of the resulting text.
let selection = selectedTextRange
// text = prospectiveText.substring(with:Range<String.Index>
(prospectiveText.startIndex ..< prospectiveText.index(after: maxLength))
let s = prospectiveText
// Get range 4 places from the start, and 6 from the end.
let c = s.characters;
let r = c.index(c.startIndex, offsetBy: 0)..<c.index(c.endIndex, offsetBy: maxLength - c.count)
text = s[r]
// Access the string by the range.
selectedTextRange = selection
}
}
or download here - >TextField.swift

Resources