NSStringの全角/半角バリデーションチェック
某アプリにクレジットカード決済をつける際に、カード名義人入力欄で全角入力をはじく必要があり、ググってみたところ意外と「全角文字と半角文字を判定する方法」はあんまり出てこなかったのでこちらに書いておきます。
(全角→半角の変換の話はいっぱい出てきた)
結論として、下記コードのように、
「1文字ずつURLエンコードし、文字列長が4以上だったら全角文字と判定する」
という方法でうまくいきました。
/* URLエンコード */ -(NSString *)stringByURLEncoding:(NSStringEncoding)encoding { NSArray *escapeChars = [NSArray arrayWithObjects: @";" ,@"/" ,@"?" ,@":" ,@"@" ,@"&" ,@"=" ,@"+" ,@"$" ,@"," ,@"[" ,@"]" ,@"#" ,@"!" ,@"'" ,@"(" ,@")" ,@"*" ,nil]; NSArray *replaceChars = [NSArray arrayWithObjects: @"%3B" ,@"%2F" ,@"%3F" ,@"%3A" ,@"%40" ,@"%26" ,@"%3D" ,@"%2B" ,@"%24" ,@"%2C" ,@"%5B" ,@"%5D" ,@"%23" ,@"%21" ,@"%27" ,@"%28" ,@"%29" ,@"%2A" ,nil]; NSMutableString *encodedString = [[[self stringByAddingPercentEscapesUsingEncoding:encoding] mutableCopy] autorelease]; for(int i=0; i<[escapeChars count]; i++) { [encodedString replaceOccurrencesOfString:[escapeChars objectAtIndex:i] withString:[replaceChars objectAtIndex:i] options:NSLiteralSearch range:NSMakeRange(0, [encodedString length])]; } return [NSString stringWithString: encodedString]; } /* 入力文字列を1文字ずつURLエンコードし、文字列長が4以上だったら全角文字と判定 */ + (BOOL)isOnlyHalf:(NSString *)str { for(int i=0; i<[str length]; i++) { NSString *aChar = [str substringWithRange:NSMakeRange(i, 1)]; NSString *encodedChar = [aChar stringByURLEncoding:NSUTF8StringEncoding]; if ([encodedChar length] < 4) { continue; } else { return NO; } } return YES; }
うまくいかなかった方法その1
ちなみに、NSCharacterSetで英数字のセットを作って判定する方法を最初に試したのですが、うまくいきませんでした。
/* 入力文字列が半角英数字と半角スペースのいずれかの文字を含む場合はYESを返す */ + (BOOL)isHalfChar:(NSString *)str { NSMutableCharacterSet *charSet = [NSMutableCharacterSet alphanumericCharacterSet]; [charSet formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; NSRange range = [str rangeOfCharacterFromSet:charSet]; if (range.location == NSNotFound) { return NO; } return YES; } /* 1文字ずつisHalfCharで判定を行う */ + (BOOL)isOnlyHalf:(NSString *)str { for (int i=0; i<[str length]; i++) { NSString *aChar = [str substringWithRange:NSMakeRange(i, 1)]; if (![Hoge isHalfChar:aChar]) { return NO; } } return YES; }
全角文字を入れても、rangeOfCharacterFromSet:で、先頭文字が検索結果として返ってきてしまい、NG。
うまくいかなかった方法その2
全角文字を文字コードで指定して判定する方法もうまくいきませんでした。
/* 全角文字のいずれかであればNOを返す(半角カナはYESを返す)*/ + (BOOL) isHalfChar:(NSString *)aValue { NSRange match = [aValue rangeOfString:@"[\x20-\x7E\xA1-\xDF]" options:NSRegularExpressionSearch]; if (match.location != NSNotFound) { return YES; } return NO; } /* 1文字ずつisHalfCharで判定を行う */ + (BOOL)isOnlyHalf:(NSString *)str { for (int i=0; i<[str length]; i++) { NSString *aChar = [str substringWithRange:NSMakeRange(i, 1)]; if (![Hoge isHalfChar:aChar]) { return NO; } } return YES; }
英数字のセットを判定する方法と同様、全角文字を入れても、rangeOfString:で、NSNotFoundにならず、NG。
(いや、ちがう挙動だったかも。とにかくNGでした)
というわけで、結論として一番上の、「エンコードして文字列長を判定する」方法をご使用ください。