Deleting Emoji Bug - ios

I followed this link Find out if Character in String is emoji? to try to limit the amount of characters my text field even with emojis. According to this link, I have to count emojis based on their glyphs and everything is working except for one little bug, when my glyph count is reached, it won't let me delete the string anymore.
Here's the code the handle the character limit using UITextField Delegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
var canEditString : Bool = false
if textField == self.descTxtField {
// Description Text Field
if textField.text != nil || textField.text != "" {
let currentString = textField.text
if (currentString?.containsEmoji)! {
print("I have an emoji")
let glyphCount = currentString!.glyphCount
print(glyphCount)
canEditString = glyphCount <= descriptionLimit
}else {
print("I have no emoji's")
let currentCharacterCount = textField.text?.characters.count ?? 0
//print(currentCharacterCount)
if (range.length + range.location > currentCharacterCount){
return false
}
let newLength = currentCharacterCount + string.characters.count - range.length
canEditString = newLength <= descriptionLimit
}
}
return canEditString
} else {
// Number Text Field
let currentCharacterCount = textField.text?.characters.count ?? 0
if (range.length + range.location > currentCharacterCount){
return false
}
let newLength = currentCharacterCount + string.characters.count - range.length
return newLength <= numberLimit
}
}

String Manifesto
Swift 4
Emojis now have a character count of 1, making it a lot easier to keep track of character counts in Strings.

Related

Issue with restrict limit characters & restrict special charecters in swift?

I am creating a OTP Screen on that screen i have added 6 text fields.Now i want to restrict to enter only ONE charecter & also want to restrict user not to enter any special charecters.Below is the code i have used,Please review the code & let me know what is wrong ?
let notAllowedCharacters = "!##$%^&*()_+{},./[]?:;";
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,replacementString string: String) -> Bool
{
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
if newLength <= 1 {
return true
}
else {
let set = NSCharacterSet(charactersIn: notAllowedCharacters);
let filtered = string.components(separatedBy: set as CharacterSet).joined(separator: "")
return filtered == string;
}
}
You need to add the control of your NSCharacterSet when you make the check for the characters length. Otherwise it will always be true regardless character if there is always one character. Update your code to the following and it will work for you:
func textField(_ textField: UITextField, shouldChangeCharactersIn 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 set = NSCharacterSet(charactersIn: notAllowedCharacters)
if newLength <= 1 && !(string.rangeOfCharacter(from: set as CharacterSet) != nil) {
return true
} else {
return false
}
}

How to get range of textField text till 6 characters?

I've a UITextField for entering pincode number.
My requirement is when textField character range reach to 6th character then I've to do server validation and I have to put the data in labels. If character range is less than 5 then I will pass nil value.
Below is my code :-
//TextField character range
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == pinCode
{
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
if(5 >= newLength)
{
print(newLength)
}
else
{
if newLength == 6
{
serverValidation()
print(textField.text!)
setFields(city: "Ajmer", state: "Rajasthan", country: "India")
return newLength <= 6
}
else
{
return newLength <= 6
}
}
}
return true
}
My problem is when (newLength == 6) then I'm getting textField text of 5 characters only. I mean if suppose zip code is 560068 then text I'm getting 56006 only. (But I've to do server validation in that condition only for 6 characters zip code)
So if (newLength == 6) then how can I get 6 characters in text field, and then I can do server validation here only.
I'm new in swift.
Thanks
shouldChangeCharactersIn will get called prior to getting the actual text in the UITextField
This is how you get the full text from that UITextField
let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)
Edit
this is how you can use it
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == pinCode
{
guard let text = textField.text else { return true }
let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)
let newLength = newString.characters.count
if(5 >= newLength)
{
print(newLength)
}
else
{
if newLength == 6
{
serverValidation()
print(newString)
setFields(city: "Ajmer", state: "Rajasthan", country: "India")
return newLength <= 6
}
else
{
return newLength <= 6
}
}
}
return true
}
Use TextField delegates method for this.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentCharacterCount = textField.text?.characters.count ?? 0
if (range.length + range.location > currentCharacterCount+1)
{
return false
}
print(currentCharacterCount)
let newLength = currentCharacterCount + string.characters.count - range.length
return newLength <= 6 //this will not allow you to enter more than 6 characters
}
After that call
func textFieldDidEndEditing(_ textField: UITextField)
{
print(textField.text!)
setFields(city: "Ajmer", state: "Rajasthan", country: "India")
}
to call this method you can use view.endEditing(true) method.
You should get newlength from textfield.text.length + string.length
then get the text from textfield.text + string.
You can't get new text from textfield.text before call return true.
Try this
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == pinCode
{
guard let text = textField.text else { return true }
var txtAfterUpdate:NSString = textField.text! as NSString
txtAfterUpdate = txtAfterUpdate.stringByReplacingCharactersInRange(range, withString: string)
let txtString = txtAfterUpdate as String
let newLength = txtString.characters.count
if(5 >= newLength)
{
print(newLength)
}
else
{
if newLength == 6
{
print(textField.text!)
setFields(city: "Ajmer", state: "Rajasthan", country: "India")
return newLength <= 6
}
else
{
return newLength <= 6
}
}
}
return true
}

Using `textField:shouldChangeCharactersInRange:`, how do i found that characters are mismatch?

I'm using the code below for setting validation of textfield as it should not enter above 15 character length .
let limitLength = 15
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// set maximum length for password and confirm password
if textField == txtPassword { // if textfield password is editing
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= limitLength
} else if textField == txtConfirmpassword { // if textfield confirm password is editing
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count - range.length
return newLength <= limitLength
}
return true
}
there are two textfield as password and confirm password
i want to check validation whether they have same string or not?
"textField:shouldChangeCharactersInRange" is method we need to use but i don't know how to compare while user is entering and i need to display alert message that they are not same
Note :- it should not compare while click on any button.
try like this
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// set maximum length for password and confirm password
if textField == txtPassword { // if textfield password is editing
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count
return newLength <= limitLength
} else if textField == txtConfirmpassword { // if textfield confirm password is editing
guard let text = textField.text else { return true }
let newLength = text.characters.count + string.characters.count
if newLength <= limitLength && txtPassword.text.hasPrefix("\(text)\(string)") {
return true
} else {
// here u can show alert
textField.resignFirstResponder()
return false
}
}
return true
}

Set UITextField to mm-dd-yy format in swift

So I want to have a UITextField to only accept digits, solved that by using a custom keyboard input.
The intention of this UITextField is to get someones birthday. I don't want to use an UIDatePicker tough as I don't like it's appearance.
I'd like that the TextField automatically inserts dashes after every second digit that the user put into the TextField.
dd-mm-yy is the placeholder text. I either thought of making the dashes permanently but I don't know how to do that either.
How can I do this?
You want to allow user to enter text in textfield in this dd-mm-yy right ?
if it so i'am sure this will help you.
In top of your class declare this variable which we gonna use later.
var dateFormate = Bool()
Add delegate and tag for that textfield.
Then add this following delegate method
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
//2. this one helps to make sure that user enters only numeric characters and '-' in fields
let numbersOnly = NSCharacterSet(charactersInString: "1234567890-")
let characterSetFromTextField = NSCharacterSet(charactersInString: string)
let Validate:Bool = numbersOnly .isSupersetOfSet(characterSetFromTextField)
if !Validate {
return false;
}
if range.length + range.location > textField.text?.characters.count {
return false
}
let newLength = (textField.text?.characters.count)! + string.characters.count - range.length
if newLength == 3 || newLength == 6 {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
dateFormate = false;
}else{
dateFormate = true;
}
if dateFormate {
let textContent:String!
textContent = textField.text
//3.Here we add '-' on overself.
let textWithHifen:NSString = "\(textContent)-"
textField.text = textWithHifen as String
dateFormate = false
}
}
//4. this one helps to make sure only 8 character is added in textfield .(ie: dd-mm-yy)
return newLength <= 8;
}
return true
}
That's it now user can enter their DOB.No need to worry about '-' it will be added automatically.
Swift 3:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
//1. To make sure that this is applicable to only particular textfield add tag.
if textField.tag == 1 {
//2. this one helps to make sure that user enters only numeric characters and '-' in fields
let numbersOnly = CharacterSet(charactersIn: "1234567890-")
let Validate = string.rangeOfCharacter(from: numbersOnly.inverted) == nil ? true : false
if !Validate {
return false;
}
if range.length + range.location > textField.text?.characters.count {
return false
}
let newLength = (textField.text?.characters.count)! + string.characters.count - range.length
if newLength == 3 || newLength == 6 {
let char = string.cString(using: NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\\b")
if (isBackSpace == -92) {
dateFormate = false;
}else{
dateFormate = true;
}
if dateFormate {
let textContent:String!
textContent = textField.text
//3.Here we add '-' on overself.
let textWithHifen:NSString = "\(textContent)-"
textField.text = textWithHifen as String
dateFormate = false
}
}
//4. this one helps to make sure only 8 character is added in textfield .(ie: dd-mm-yy)
return newLength <= 8;
}
return true
}
Swift5
// Use textfield delegate shouldChangeCharactersIn
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if (textField.text?.count == 2) || (textField.text?.count == 5) {
if !(string == "") {
textField.text = (textField.text)! + "-"
}
}
return !(textField.text!.count > 7 && (string.count ) > range.length)
}

Swift UITextField Decimal Field Type - No Pasting, 1 Decimal Point Only and Length Limit

I am trying to do some error checking for an text field which will only accept a decimal value. This means that the text field cannot be pasted into, the user can only enter 1 decimal point and my personal preference I want a length limit of 2 characters after the decimal place.
I have got the current code which simply restricts the paste:
//Does not allow pasting into text field
//https://stackoverflow.com/questions/26919854/how-can-i-declare-that-a-text-field-can-only-contain-an-integer
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let invalidCharacters = NSCharacterSet(charactersInString: "0123456789.").invertedSet
return string.rangeOfCharacterFromSet(invalidCharacters, options: [], range: string.startIndex ..< string.endIndex) == nil
}
It works, but I want other features as well. How can I implement these?
To check whether It has a decimal point and limit 2 decimal place you can use like this :-
let str = "456.23" // Your Label Value
let nsStr = NSString(string: str) // Conver label value to NSString
let strSplit = str.characters.split(".") // split label before decimal point and after decimal point
if str.containsString(".") {
//Contains Decimal value
if String(strSplit.last!).characters.count <= 2 {
// Contains 2 or 1 decimal values
} else {
// More than 2 decimal values
}
} else {
//Do not contains Decimal value
}
you can do something like,
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var dotLocation = Int()
let nonNumberSet = NSMutableCharacterSet() //create an empty mutable set
nonNumberSet.formUnionWithCharacterSet(NSCharacterSet.URLQueryAllowedCharacterSet())
nonNumberSet.addCharactersInString("0123456789.")
//allow backspace
if range.length == 0 && string.characters.count == 0
{
return true
}
if string == "."
{
if range.location == 0{
return false
}
if dotLocation == 0 {
dotLocation == range.location
return true
}
else{
return false
}
}
if range.location == dotLocation && string.characters.count == 0{
dotLocation = 0
}
var newStr = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
newStr = (newStr.componentsSeparatedByCharactersInSet(nonNumberSet) as NSArray).componentsJoinedByString("")
textField.text = newStr
return false
}
Hope this will help :)

Resources