textfielddidchange style delegate iphone objective-c ios uitextfield

iphone - style - uitextfield delegate



Formato UITextField en xx-xx-xxx (9)

Aquí está mi opinión después de ver las respuestas de todos.

Swift 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let separator = "-" let filler = "X" if var number = textField.text, string != "" { number = number.replacingOccurrences(of: separator, with: "") number = number.replacingOccurrences(of: filler, with: "") if number.count == 10 { return false } number += string while number.count < 10 { number += "X" } number.insert("-", at: number.index(number.startIndex, offsetBy: 6)) number.insert("-", at: number.index(number.startIndex, offsetBy: 3)) textField.text = number } return false }

Estoy usando UITextField y quiero que tenga carácter en el formato de xx-xx-xxx solo números.

alguna ayuda ?


Implemente su lógica dentro de textField:shouldChangeCharactersInRange:replacementString: que es un método delegado.


Intenta a continuación funcionará

C objetivo

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { int groupingSize = 2; if([string length] == 0) { groupingSize = 4; } NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init] ; NSString *separator = @"-"; [formatter setGroupingSeparator:separator]; [formatter setGroupingSize:groupingSize]; [formatter setUsesGroupingSeparator:YES]; [formatter setSecondaryGroupingSize:2]; if (![string isEqual: @""] && (textField.text != nil && textField.text.length > 0)) { NSString *num = textField.text; num = [num stringByReplacingOccurrencesOfString:separator withString:@""]; NSString *str = [formatter stringFromNumber:[NSNumber numberWithDouble:[num doubleValue]]]; textField.text = str; } return YES; }

Swift-3

extension ViewController: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { var groupSize = 2 let separator = "-" if string.characters.count == 0 { groupSize = 4 } let formatter = NumberFormatter() formatter.groupingSeparator = separator formatter.groupingSize = groupSize formatter.usesGroupingSeparator = true formatter.secondaryGroupingSize = 2 if var number = textField.text, string != "" { number = number.replacingOccurrences(of: separator, with: "") if let doubleVal = Double(number) { let requiredString = formatter.string(from: NSNumber.init(value: doubleVal)) textField.text = requiredString } } return true } }


Mi solución funciona así:

Implementar en sus delegados de campo de texto:

func textFieldDidBeginEditing(_ textField: UITextField) { // When you start editing check if there is nothing, in that case add the entire mask if let text = textField.text, text == "" || text == "DD/MM/YYYY" { textField.text = "DD/MM/YYYY" textField.textColor = .lightGray textField.setCursor(position: text.count) } } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard var number = textField.text else { return true } // If user try to delete, remove the char manually if string == "" { number.remove(at: number.index(number.startIndex, offsetBy: range.location)) } // Remove all mask characters number = number.replacingOccurrences(of: "/", with: "") number = number.replacingOccurrences(of: "D", with: "") number = number.replacingOccurrences(of: "M", with: "") number = number.replacingOccurrences(of: "Y", with: "") // Set the position of the cursor var cursorPosition = number.count+1 if string == "" { //if it''s delete, just take the position given by the delegate cursorPosition = range.location } else { // If not, take into account the slash if cursorPosition > 2 && cursorPosition < 5 { cursorPosition += 1 } else if cursorPosition > 4 { cursorPosition += 2 } } // Stop editing if we have rich the max numbers if number.count == 8 { return false } // Readd all mask char number += string while number.count < 8 { if number.count < 2 { number += "D" } else if number.count < 4 { number += "M" } else { number += "Y" } } number.insert("/", at: number.index(number.startIndex, offsetBy: 4)) number.insert("/", at: number.index(number.startIndex, offsetBy: 2)) // Some styling let enteredTextAttribute = [NSForegroundColorAttributeName: UIColor.black, NSFontAttributeName: UIFont.systemFont(ofSize: 15)] let maskTextAttribute = [NSForegroundColorAttributeName: UIColor.lightGray, NSFontAttributeName: UIFont.systemFont(ofSize: 15)] let partOne = NSMutableAttributedString(string: String(number.prefix(cursorPosition)), attributes: enteredTextAttribute) let partTwo = NSMutableAttributedString(string: String(number.suffix(number.count-cursorPosition)), attributes: maskTextAttribute) let combination = NSMutableAttributedString() combination.append(partOne) combination.append(partTwo) textField.attributedText = combination textField.setCursor(position: cursorPosition) return false } func textFieldDidEndEditing(_ textField: UITextField) { if let text = textField.text, text != "" && text != "DD/MM/YYYY" { // Do something with your value } else { textField.text = "" } }

Y ese pequeño ayudante como extensión:

extension UITextField { func setCursor(position: Int) { let position = self.position(from: beginningOfDocument, offset: position)! selectedTextRange = textRange(from: position, to: position) } }

PD: todavía hay un error en esa implementación cuando intentas mover el cursor al editar


Mis búsquedas en google me dicen que deberías implementar

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

desde el protocolo UITextFieldDelegate .

Echa un vistazo a this para más información.


Puede llamar a path en este método cualquier patrón que necesite para su textField:

extension String { func applyPatternOnNumbers(pattern: String, replacmentCharacter: Character) -> String { var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression) for index in 0 ..< pattern.count { guard index < pureNumber.count else { return pureNumber } let stringIndex = String.Index(encodedOffset: index) let patternCharacter = pattern[stringIndex] guard patternCharacter != replacmentCharacter else { continue } pureNumber.insert(patternCharacter, at: stringIndex) } return pureNumber } }

Ejemplo:

guard let text = textField.text else { return } textField.text = text.applyPatternOnNumbers(pattern: "##-##-###", replacmentCharacter: "#")


Si quieres que sea algo así como una fecha, puedes crear tu propio formateador de fechas como este:

NSDateFormatter *formatter; NSString *dateString; formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"dd-MM-yyyy HH:mm"]; //or something in your own style dateString = [formatter stringFromDate:[NSDate date]]; [formatter release]; // maybe; you might want to keep the formatter // if you''re doing this a lot.

Obtención de la hora actual en cadena en formato personalizado en el objetivo c


Tenía la necesidad de hacer esto bien para un número de teléfono con un formato variable, esto es lo que escribí. Siéntase libre de reutilizarlo. Primero, tengo un método para filtrar una cadena formateada, donde # es un número, y cualquier otro carácter es algún tipo de "relleno" que debe insertarse convenientemente una vez que el usuario llega al lugar donde lo necesita. .

NSMutableString *filteredPhoneStringFromStringWithFilter(NSString *string, NSString *filter) { NSUInteger onOriginal = 0, onFilter = 0, onOutput = 0; char outputString[([filter length])]; BOOL done = NO; while(onFilter < [filter length] && !done) { char filterChar = [filter characterAtIndex:onFilter]; char originalChar = onOriginal >= string.length ? ''/0'' : [string characterAtIndex:onOriginal]; switch (filterChar) { case ''#'': if(originalChar==''/0'') { // We have no more input numbers for the filter. We''re done. done = YES; break; } if(isdigit(originalChar)) { outputString[onOutput] = originalChar; onOriginal++; onFilter++; onOutput++; } else { onOriginal++; } break; default: // Any other character will automatically be inserted for the user as they type (spaces, - etc..) or deleted as they delete if there are more numbers to come. outputString[onOutput] = filterChar; onOutput++; onFilter++; if(originalChar == filterChar) onOriginal++; break; } } outputString[onOutput] = ''/0''; // Cap the output string return [NSString stringWithUTF8String:outputString]; }

Ahora, para que puedan eliminarse a través del relleno, modifiqué mi cambio de caracteres en el rango.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSString *filter = @"(###) ### - ####"; if(!filter) return YES; // No filter provided, allow anything NSString *changedString = [textField.text stringByReplacingCharactersInRange:range withString:string]; if(range.length == 1 && // Only do for single deletes string.length < range.length && [[textField.text substringWithRange:range] rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789"]].location == NSNotFound) { // Something was deleted. Delete past the previous number NSInteger location = changedString.length-1; if(location > 0) { for(; location > 0; location--) { if(isdigit([changedString characterAtIndex:location])) { break; } } changedString = [changedString substringToIndex:location]; } } textField.text = filteredPhoneStringFromStringWithFilter(changedString, filter); return NO; }

Esto proporciona una manera realmente limpia de obligar a los usuarios a ingresar números en un formato particular.


Tipo rápido de método largo, pero funciona bien: iOS 8

ViewController // marca de programación ----- ----- ---- ----- ----- ---- ----- ----- ----

override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.tfCardNumber.addTarget(self, action: "creditCardNumberFormatter:", forControlEvents: .EditingChanged) self.tfExpiryValue.addTarget(self, action: "creditCardExpiryFormatter:", forControlEvents: .EditingChanged) }// end viewDidAppear func creditCardNumberFormatter(sender: AnyObject!) { // create object universally access global methods var objMethodInc = MethodInc(object: self) var formattedText = objMethodInc.formatCreditCard(self.tfCardNumber.text) if formattedText != self.tfCardNumber.text { self.tfCardNumber.text = formattedText } if countElements(self.tfCardNumber.text) == 19 { self.tfCardNumber.resignFirstResponder() self.tfExpiryValue.becomeFirstResponder() } }// end creditCardNumberFormatter func creditCardExpiryFormatter(sender: AnyObject!) { // create object universally access global methods var objMethodInc = MethodInc(object: self) var formattedText = objMethodInc.formatCreditCardExpiry(self.tfExpiryValue.text) if formattedText != self.tfExpiryValue.text { self.tfExpiryValue.text = formattedText } }// end creditCardExpiryFormatter

// marca de prgm --- ---- --- ----

// delegate for textfield func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange , replacementString string: String) -> Bool { if string == "" { return true } if textField == self.tfCardNumber { if countElements(self.tfCardNumber.text) > 18 { return false } else if textField == self.tfExpiryValue { if countElements(self.tfExpiryValue.text) > 4 { return false } } } return true }// end textField

----------- DENTRO de su método de comando o archivo --------

// marca de prgm ----

func formatCreditCard(input: NSString) -> String { var input = self.trimSpecialCharacters(input); println("formatCreditCard input /(input)") var output : NSString? switch (input.length) { case 1: output = input case 2: output = input case 3: output = input case 4: var vs = input.substringToIndex(input.length) output = NSString(string: "/(vs)") break case 5: output = input case 6: output = input case 7: output = input case 8: var vs1 = input.substringToIndex(4) var vs2 = input.substringFromIndex(4) output = NSString(string: "/(vs1)-/(vs2)") break case 9: output = input case 10: output = input case 11: output = input case 12: var vs1 = input.substringToIndex(4) var vs2 = input.substringWithRange(NSMakeRange(4, 4)) var vs3 = input.substringFromIndex(8) output = NSString(string: "/(vs1)-/(vs2)-/(vs3)") break case 13: output = input case 14: output = input case 15: output = input case 16: var vs1 = input.substringToIndex(4) var vs2 = input.substringWithRange(NSMakeRange(4, 4)) var vs3 = input.substringWithRange(NSMakeRange(8, 4)) var vs4 = input.substringFromIndex(12) output = NSString(string: "/(vs1)-/(vs2)-/(vs3)-/(vs4)") break default: output = input break }// end switch println("formatCreditCard out /(output!)") return output! }// end formatCreditCard // prgm mark ---- func formatCreditCardExpiry(input: NSString) -> String { var output : NSString? var input = self.trimSpecialCharacters(input); switch (input.length) { case 1: output = input case 2: var vs = input.substringToIndex(input.length) output = NSString(string: "/(vs)") break case 3: output = input case 4: var vs1 = input.substringToIndex(2) var vs2 = input.substringFromIndex(2) output = NSString(string: "/(vs1)//(vs2)") break default: output = input break } return output! }// end formatCreditCardExpiry func trimSpecialCharacters(input: NSString) -> NSString { var special = NSCharacterSet(charactersInString: "/+-() ") var comp = input.componentsSeparatedByCharactersInSet(special) as NSArray return comp.componentsJoinedByString("") }//end trimSpecialCharacters