ひらがなを半角カタカナに変換する処理と、半角英数字を全角英数字に変換する処理を持つアプリがインストールされていたiPadをiOS6.0にバージョンアップしたところ、この2つの処理がうまく動かなくなりました。
結論から言うと簡単な回避策はなく、iOSのバージョンアップを待てない場合は自前で変換処理を作成する必要があると思います。
今回問題となったアプリでは、下記の2種類の処理を CFStringTransform() を使って作成しています。
(1)入力されたひらがな半角カタカナに変換する処理
(2)入力された半角英数字を全角英数字に変換する処理
ちなみに(1)の半角カタカナにする処理では、途中でいったん全角カタカナに変換するので CFStringTransform() を2段階かけています。
CFStringTransform() についてググってみると、どうもiOS6.0SDKのバグっぽい感じがしました。
iOS6.0SDKのCFStringTransform()
ユーザーからのレポートでは「同じ操作を2回繰り返すと処理される」というような話がありましたので、2回繰り返すようにしたところ、たしかに(1)の半角カタカナに変換する処理はどうにか動くようになりました。1回ではダメで2回やるとうまくというところが、バグっぽいです。
修正前
NSMutableString *convertedString = [[textArea text] mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)convertedString, NULL, kCFStringTransformHiraganaKatakana, false);
CFStringTransform((__bridge CFMutableStringRef)convertedString, NULL, kCFStringTransformFullwidthHalfwidth, false);
修正後
NSMutableString *convertedString = [[textArea text] mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)convertedString, NULL, kCFStringTransformHiraganaKatakana, false);
CFStringTransform((__bridge CFMutableStringRef)convertedString, NULL, kCFStringTransformFullwidthHalfwidth, false);
NSMutableString *convertedString2 = [[textArea text] mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)convertedString2, NULL, kCFStringTransformHiraganaKatakana, false);
CFStringTransform((__bridge CFMutableStringRef)convertedString2, NULL, kCFStringTransformFullwidthHalfwidth, false);
ただし、この同じ処理を2回繰り返すというやり方では、(2)の半角文字列を全角にするという処理ではうまくいきませんでした。(1回目はうまくいくが2回目以降は逆に半角に変換されてしまう)。
そこで、NSStringクラスに全角文字列変換を行う処理をカテゴリで追加することにしました。変なところにiOSのバグが潜んでいると困るので、文字をひとつひとつチェックして差し替えるというベタな方法で記述しました。
下記にソースコードを掲載しますが限られた時間の中で作成したものであり、動作について細かくチェックしてある訳ではないので、参考程度にしていただければと思います。またこのサンプルでは「ガギグゲゴ」などの濁音、半濁音については特に考慮してありませんので、用途によってはうまく修正していただく必要があります。
//
// NSString+Zenkaku.h
// Proto01
//
// Created by 竹下 治彦 on 12/10/11.
//
//
#import
// NSStringクラスを拡張し全角文字列に変換して返す機能をカテゴリとして追加
@interface NSString(Zenkaku)
– (NSString *)mojiToZenkaku:(NSString *)moji;
– (NSString *)convertToZenkaku;
@end
//
// NSString+Zenkaku.m
// Proto01
//
// Created by 竹下 治彦 on 12/10/11.
//
//
#import “NSString+Zenkaku.h”
@implementation NSString(Zenkaku)
//渡された文字に対応する全角文字を返す
– (NSString *)mojiToZenkaku:(NSString *)moji
{
if([moji isEqualToString:@” “]) return @” ”;
if([moji isEqualToString:@”!”]) return @”!”;
if([moji isEqualToString:@”\””]) return @”””;
if([moji isEqualToString:@”#”]) return @”#”;
if([moji isEqualToString:@”$”]) return @”$”;
if([moji isEqualToString:@”%”]) return @”%”;
if([moji isEqualToString:@”&”]) return @”&”;
if([moji isEqualToString:@”‘”]) return @”’”;
if([moji isEqualToString:@”(“]) return @”(”;
if([moji isEqualToString:@”)”]) return @”)”;
if([moji isEqualToString:@”*”]) return @”*”;
if([moji isEqualToString:@”+”]) return @”+”;
if([moji isEqualToString:@”,”]) return @”,”;
if([moji isEqualToString:@”-“]) return @”-”;
if([moji isEqualToString:@”.”]) return @”.”;
if([moji isEqualToString:@”/”]) return @”/”;
if([moji isEqualToString:@”0″]) return @”0”;
if([moji isEqualToString:@”1″]) return @”1”;
if([moji isEqualToString:@”2″]) return @”2”;
if([moji isEqualToString:@”3″]) return @”3”;
if([moji isEqualToString:@”4″]) return @”4”;
if([moji isEqualToString:@”5″]) return @”5”;
if([moji isEqualToString:@”6″]) return @”6”;
if([moji isEqualToString:@”7″]) return @”7”;
if([moji isEqualToString:@”8″]) return @”8”;
if([moji isEqualToString:@”9″]) return @”9”;
if([moji isEqualToString:@”:”]) return @”:”;
if([moji isEqualToString:@”;”]) return @”;”;
if([moji isEqualToString:@”<"]) return @"<"; if([moji isEqualToString:@"="]) return @"="; if([moji isEqualToString:@">“]) return @”>”;
if([moji isEqualToString:@”?”]) return @”?”;
if([moji isEqualToString:@”@”]) return @”@”;
if([moji isEqualToString:@”A”]) return @”A”;
if([moji isEqualToString:@”B”]) return @”B”;
if([moji isEqualToString:@”C”]) return @”C”;
if([moji isEqualToString:@”D”]) return @”D”;
if([moji isEqualToString:@”E”]) return @”E”;
if([moji isEqualToString:@”F”]) return @”F”;
if([moji isEqualToString:@”G”]) return @”G”;
if([moji isEqualToString:@”H”]) return @”H”;
if([moji isEqualToString:@”I”]) return @”I”;
if([moji isEqualToString:@”J”]) return @”J”;
if([moji isEqualToString:@”K”]) return @”K”;
if([moji isEqualToString:@”L”]) return @”L”;
if([moji isEqualToString:@”M”]) return @”M”;
if([moji isEqualToString:@”N”]) return @”N”;
if([moji isEqualToString:@”O”]) return @”O”;
if([moji isEqualToString:@”P”]) return @”P”;
if([moji isEqualToString:@”Q”]) return @”Q”;
if([moji isEqualToString:@”R”]) return @”R”;
if([moji isEqualToString:@”S”]) return @”S”;
if([moji isEqualToString:@”T”]) return @”T”;
if([moji isEqualToString:@”U”]) return @”U”;
if([moji isEqualToString:@”V”]) return @”V”;
if([moji isEqualToString:@”W”]) return @”W”;
if([moji isEqualToString:@”X”]) return @”X”;
if([moji isEqualToString:@”Y”]) return @”Y”;
if([moji isEqualToString:@”Z”]) return @”Z”;
if([moji isEqualToString:@”[“]) return @”[”;
if([moji isEqualToString:@”\\”]) return @”¥”;
if([moji isEqualToString:@”]”]) return @”]”;
if([moji isEqualToString:@”^”]) return @”^”;
if([moji isEqualToString:@”_”]) return @”_”;
if([moji isEqualToString:@”`”]) return @”‘”;
if([moji isEqualToString:@”a”]) return @”a”;
if([moji isEqualToString:@”b”]) return @”b”;
if([moji isEqualToString:@”c”]) return @”c”;
if([moji isEqualToString:@”d”]) return @”d”;
if([moji isEqualToString:@”e”]) return @”e”;
if([moji isEqualToString:@”f”]) return @”f”;
if([moji isEqualToString:@”g”]) return @”g”;
if([moji isEqualToString:@”h”]) return @”h”;
if([moji isEqualToString:@”i”]) return @”i”;
if([moji isEqualToString:@”j”]) return @”j”;
if([moji isEqualToString:@”k”]) return @”k”;
if([moji isEqualToString:@”l”]) return @”l”;
if([moji isEqualToString:@”m”]) return @”m”;
if([moji isEqualToString:@”n”]) return @”n”;
if([moji isEqualToString:@”o”]) return @”o”;
if([moji isEqualToString:@”p”]) return @”p”;
if([moji isEqualToString:@”q”]) return @”q”;
if([moji isEqualToString:@”r”]) return @”r”;
if([moji isEqualToString:@”s”]) return @”s”;
if([moji isEqualToString:@”t”]) return @”t”;
if([moji isEqualToString:@”u”]) return @”u”;
if([moji isEqualToString:@”v”]) return @”v”;
if([moji isEqualToString:@”w”]) return @”w”;
if([moji isEqualToString:@”x”]) return @”x”;
if([moji isEqualToString:@”y”]) return @”y”;
if([moji isEqualToString:@”z”]) return @”z”;
if([moji isEqualToString:@”{“]) return @”{”;
if([moji isEqualToString:@”|”]) return @”|”;
if([moji isEqualToString:@”}”]) return @”}”;
if([moji isEqualToString:@”~”]) return @” ̄”;
if([moji isEqualToString:@”。”]) return @”。”;
if([moji isEqualToString:@”「”]) return @”「”;
if([moji isEqualToString:@”」”]) return @”」”;
if([moji isEqualToString:@”、”]) return @”、”;
if([moji isEqualToString:@”・”]) return @”・”;
if([moji isEqualToString:@”ヲ”]) return @”ヲ”;
if([moji isEqualToString:@”ァ”]) return @”ァ”;
if([moji isEqualToString:@”ィ”]) return @”ィ”;
if([moji isEqualToString:@”ゥ”]) return @”ゥ”;
if([moji isEqualToString:@”ェ”]) return @”ェ”;
if([moji isEqualToString:@”ォ”]) return @”ォ”;
if([moji isEqualToString:@”ャ”]) return @”ャ”;
if([moji isEqualToString:@”ュ”]) return @”ュ”;
if([moji isEqualToString:@”ョ”]) return @”ョ”;
if([moji isEqualToString:@”ッ”]) return @”ッ”;
if([moji isEqualToString:@”ー”]) return @”ー”;
if([moji isEqualToString:@”ア”]) return @”ア”;
if([moji isEqualToString:@”イ”]) return @”イ”;
if([moji isEqualToString:@”ウ”]) return @”ウ”;
if([moji isEqualToString:@”エ”]) return @”エ”;
if([moji isEqualToString:@”オ”]) return @”オ”;
if([moji isEqualToString:@”カ”]) return @”カ”;
if([moji isEqualToString:@”キ”]) return @”キ”;
if([moji isEqualToString:@”ク”]) return @”ク”;
if([moji isEqualToString:@”ケ”]) return @”ケ”;
if([moji isEqualToString:@”コ”]) return @”コ”;
if([moji isEqualToString:@”サ”]) return @”サ”;
if([moji isEqualToString:@”シ”]) return @”シ”;
if([moji isEqualToString:@”ス”]) return @”ス”;
if([moji isEqualToString:@”セ”]) return @”セ”;
if([moji isEqualToString:@”ソ”]) return @”ソ”;
if([moji isEqualToString:@”タ”]) return @”タ”;
if([moji isEqualToString:@”チ”]) return @”チ”;
if([moji isEqualToString:@”ツ”]) return @”ツ”;
if([moji isEqualToString:@”テ”]) return @”テ”;
if([moji isEqualToString:@”ト”]) return @”ト”;
if([moji isEqualToString:@”ナ”]) return @”ナ”;
if([moji isEqualToString:@”ニ”]) return @”ニ”;
if([moji isEqualToString:@”ヌ”]) return @”ヌ”;
if([moji isEqualToString:@”ネ”]) return @”ネ”;
if([moji isEqualToString:@”ノ”]) return @”ノ”;
if([moji isEqualToString:@”ハ”]) return @”ハ”;
if([moji isEqualToString:@”ヒ”]) return @”ヒ”;
if([moji isEqualToString:@”フ”]) return @”フ”;
if([moji isEqualToString:@”ヘ”]) return @”ヘ”;
if([moji isEqualToString:@”ホ”]) return @”ホ”;
if([moji isEqualToString:@”マ”]) return @”マ”;
if([moji isEqualToString:@”ミ”]) return @”ミ”;
if([moji isEqualToString:@”ム”]) return @”ム”;
if([moji isEqualToString:@”メ”]) return @”メ”;
if([moji isEqualToString:@”モ”]) return @”モ”;
if([moji isEqualToString:@”ヤ”]) return @”ヤ”;
if([moji isEqualToString:@”ユ”]) return @”ユ”;
if([moji isEqualToString:@”ヨ”]) return @”ヨ”;
if([moji isEqualToString:@”ラ”]) return @”ラ”;
if([moji isEqualToString:@”リ”]) return @”リ”;
if([moji isEqualToString:@”ル”]) return @”ル”;
if([moji isEqualToString:@”レ”]) return @”レ”;
if([moji isEqualToString:@”ロ”]) return @”ロ”;
if([moji isEqualToString:@”ワ”]) return @”ワ”;
if([moji isEqualToString:@”ン”]) return @”ン”;
if([moji isEqualToString:@”゙”]) return @”゛”;
if([moji isEqualToString:@”゚”]) return @”゜”;
//対象文字にひっかからなかったら、渡された文字をそのまま返す
return moji;
}
//渡された文字列中の半角文字列を全角に置換して返す
– (NSString *)convertToZenkaku
{
NSMutableString *target = [self mutableCopy];
for(int p = 0; p < [target length]; p++){ NSRange range = NSMakeRange(p, 1); NSString *moji = [target substringWithRange:range]; [target replaceCharactersInRange:NSMakeRange(p, 1) withString:[self mojiToZenkaku:moji]]; } return target; } @end
0件のコメント