Respuestas:
Aquí hay una forma que no depende de la precisión limitada de intentar analizar la cadena como un número:
NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
Ver +[NSCharacterSet decimalDigitCharacterSet]y -[NSString rangeOfCharacterFromSet:].
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]]
invertedSetestá devolviendo una clase que envuelve el conjunto en el que se creó y devuelve el valor opuesto para todas las consultas. Pero no lo sé con certeza.
Sugeriría usar el numberFromString:método de la clase NSNumberFormatter , como si el número no fuera válido, devolverá nil; de lo contrario, le devolverá un NSNumber.
NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease];
BOOL isDecimal = [nf numberFromString:newString] != nil;
NOpara su cadena. También vale la pena saberlo: también regresan YESpara números rellenados con espacios en blanco. Por cierto, acabo de agregar un fragmento de código real a su respuesta, espero que no le importe.
Validar por expresión regular, por patrón "^[0-9]+$", con el siguiente método -validateString:withPattern:.
[self validateString:"12345" withPattern:"^[0-9]+$"];
"^[0-9]+(.{1}[0-9]+)?$"".".
"^[0-9]{4}$".".", y la longitud está entre 2 ~ 5.
"^[0-9]{2,5}$"."^-?\d+$"La expresión regular se puede comprobar en el sitio web en línea .
La función de ayuda es la siguiente.
// Validate the input string with the given pattern and
// return the result as a boolean
- (BOOL)validateString:(NSString *)string withPattern:(NSString *)pattern
{
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
NSAssert(regex, @"Unable to create regular expression");
NSRange textRange = NSMakeRange(0, string.length);
NSRange matchRange = [regex rangeOfFirstMatchInString:string options:NSMatchingReportProgress range:textRange];
BOOL didValidate = NO;
// Did we find a matching range
if (matchRange.location != NSNotFound)
didValidate = YES;
return didValidate;
}
Prueba en el patio de recreo.
import UIKit
import Foundation
func validate(_ str: String, pattern: String) -> Bool {
if let range = str.range(of: pattern, options: .regularExpression) {
let result = str.substring(with: range)
print(result)
return true
}
return false
}
let a = validate("123", pattern: "^-?[0-9]+")
print(a)
func numberOnly(string: String) -> Int { let expression = "" let regex = NSRegularExpression.init(pattern: expression, options: .caseInsensitive) let numberOfMatches = regex.numberOfMatches(in: string, options: .reportProgress, range: NSRange.init(location: 0, length: string.characters.count)) if numberOfMatches == 0 { return Int(string)! } return 0 }Y recibí un errorPlayground execution aborted: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
return matchRange.location != NSNotFound;
^-?\d+$, lo verifiqué en el sitio: regex101.com
Puede crear un NSScanner y simplemente escanear la cadena:
NSDecimal decimalValue;
NSScanner *sc = [NSScanner scannerWithString:newString];
[sc scanDecimal:&decimalValue];
BOOL isDecimal = [sc isAtEnd];
Consulte la documentación de NSScanner para conocer más métodos entre los que elegir.
isAtEnd.
Creo que la forma más fácil de verificar que cada carácter dentro de una cadena dada sea numérico es probablemente:
NSString *trimmedString = [newString stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];
if([trimmedString length])
{
NSLog(@"some characters outside of the decimal character set found");
}
else
{
NSLog(@"all characters were in the decimal character set");
}
Utilice uno de los otros métodos de fábrica de NSCharacterSet si desea un control total sobre los caracteres aceptables.
Esta pregunta original era sobre Objective-C, pero también se publicó años antes de que se anunciara Swift. Entonces, si vienes aquí desde Google y estás buscando una solución que use Swift, aquí tienes:
let testString = "12345"
let badCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
if testString.rangeOfCharacterFromSet(badCharacters) == nil {
print("Test string was a number")
} else {
print("Test string contained non-digit characters.")
}
Solución Swift 3 si necesita verificar que la cadena solo tiene dígitos:
CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: myString))
.invertedacciones innecesarias y de otro tipo.
para ser claros, esto funciona para enteros en cadenas.
aquí hay una pequeña categoría de ayuda basada en la respuesta de John anterior:
en archivo .h
@interface NSString (NumberChecking)
+(bool)isNumber:(NSString *)string;
@end
en archivo .m
#import "NSString+NumberChecking.h"
@implementation NSString (NumberChecking)
+(bool)isNumber {
if([self rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound) {
return YES;
}else {
return NO;
}
}
@end
uso:
#import "NSString+NumberChecking.h"
if([someString isNumber]) {
NSLog(@"is a number");
}else {
NSLog(@"not a number");
}
La solución Swift 3 podría ser como:
extension String {
var doubleValue:Double? {
return NumberFormatter().number(from:self)?.doubleValue
}
var integerValue:Int? {
return NumberFormatter().number(from:self)?.intValue
}
var isNumber:Bool {
get {
let badCharacters = NSCharacterSet.decimalDigits.inverted
return (self.rangeOfCharacter(from: badCharacters) == nil)
}
}
}
La respuesta de John Calsbeek es casi correcta pero omite algunos casos de borde Unicode.
Según la documentación dedecimalDigitCharacterSet , ese conjunto incluye todos los caracteres categorizados por Unicode como Nd. Así su respuesta aceptará, entre otros:
१ (U + 0967 DEVANAGARI DIGIT ONE)᠑ (U + 1811 MONGOLIAN DIGIT ONE)𝟙 (U + 1D7D9 DÍGITO UNO MATEMÁTICO DE DOBLE CUERDA)Si bien en cierto sentido esto es correcto, cada carácter en Ndse asigna a un dígito decimal, es casi seguro que no es lo que esperaba el autor de la pregunta. En el momento de escribir este artículo, hay 610 puntos de código categorizadosNd , de los cuales solo diez son los caracteres esperados 0(U + 0030) a 9(U + 0039).
Para solucionar el problema, simplemente especifique exactamente los caracteres que son aceptables:
NSCharacterSet* notDigits =
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
Otra opción más:
- (BOOL)isValidNumber:(NSString*)text regex:(NSString*)regex {
@try {
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [predicate evaluateWithObject:text];
}
@catch (NSException *exception) {
assert(false);
return NO;
}
}
Ejemplo de uso:
BOOL isValid = [self isValidNumber:@"1234" regex:@"^[0-9]+$"];
Una extensión de la respuesta de @John Calsbeek y una aclaración de los comentarios de @Jeff y @gyratory circus .
+ (BOOL)doesContainDigitsOnly:(NSString *)string
{
NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
BOOL containsDigitsOnly = [string rangeOfCharacterFromSet:nonDigits].location == NSNotFound;
return containsDigitsOnly;
}
+ (BOOL)doesContainNonDigitsOnly:(NSString *)string
{
NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
BOOL containsNonDigitsOnly = [string rangeOfCharacterFromSet:digits].location == NSNotFound;
return containsNonDigitsOnly;
}
Los siguientes pueden agregarse como métodos de categoría para NSString
- (BOOL)doesContainDigitsOnly
{
NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
BOOL containsDigitsOnly = [self rangeOfCharacterFromSet:nonDigits].location == NSNotFound;
return containsDigitsOnly;
}
- (BOOL)doesContainNonDigitsOnly
{
NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
BOOL containsNonDigitsOnly = [self rangeOfCharacterFromSet:digits].location == NSNotFound;
return containsNonDigitsOnly;
}
Probar si una cadena es un número que podría ser útil
int i = [@"12.3" rangeOfCharacterFromSet: [ [NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] ].location;
if (i == NSNotFound) {
//is a number
}
Extensión rápida:
extension NSString {
func isNumString() -> Bool {
let numbers = NSCharacterSet(charactersInString: "0123456789.").invertedSet
let range = self.rangeOfCharacterFromSet(numbers).location
if range == NSNotFound {
return true
}
return false
} }
Para Swift 3
var onlyDigits: CharacterSet = CharacterSet.decimalDigits.inverted
if testString.rangeOfCharacter(from: onlyDigits) == nil {
// String only consist digits 0-9
}
Cuando tiene dígitos que son de idiomas mixtos , que usan (o no) los formatos de 0-9 dígitos, necesitará ejecutar una expresión regular que buscará cualquier número, lo siguiente es convertir todos los dígitos para que sean 0- 9 formato (si necesita el valor real):
// Will look for any language digits
let regex = try NSRegularExpression(pattern: "[^[:digit:]]", options: .caseInsensitive)
let digitsString = regex.stringByReplacingMatches(in: string,
options: NSRegularExpression.MatchingOptions(rawValue: 0),
range: NSMakeRange(0, string.count), withTemplate: "")
// Converting the digits to be 0-9 format
let numberFormatter = NumberFormatter()
numberFormatter.locale = Locale(identifier: "EN")
let finalValue = numberFormatter.number(from: digitsString)
if let finalValue = finalValue {
let actualValue = finalValue.doubleValue
}
La forma más fácil y confiable es intentar lanzar como Double, si el resultado es nil, no se puede convertir en un número legítimo.
let strings = ["test", "123", "123.2", "-123", "123-3", "123..22", ".02"]
let validNumbers = strings.compactMap(Double.init)
print(validNumbers)
// prints [123.0, 123.2, -123.0, 0.02]
Más información en la documentación: https://developer.apple.com/documentation/swift/double/2926277-init
.carácter