UITableView の sectionIndexTitle に日本語を使うには


CoreDataにあるエントリーがあって titleというatributeで日本語タイトルを保持している。このタイトルの最初の1文字をSection Titleにするために、titleInitialというatributeを作ってTransientにし、その最初の1文字はインプリで対応した。
以下が参考になった。
How to use the first character as a section name – ComAnswer.com

@implementation NSManagedObject (…)
– (NSString *) titleInitial {
[self willAccessValueForKey:@”titleInitial”];
NSString *aString = [[self valueForKey:@”title”] uppercaseString];
NSString * initial = [[aString substringWithRange:[aString rangeOfComposedCharacterSequenceAtIndex:0]] uppercaseString];
うんぬんかんぬんという感じ。それで
– (NSFetchedResultsController *)fetchedResultsController {
の中で
NSFetchedResultsController *resultsController;
resultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:[self managedObjectContext]
sectionNameKeyPath:@”titleInitial”
cacheName:@”Root”];
のようにsectionNameKeyPathを設定する。
それで SectionIndex が表示されるように、
– (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [fetchedResultsController_ sectionIndexTitles];
とか

-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [fetchedResultsController_ sectionForSectionIndexTitle:title atIndex:index];
とかする。

でも、section index上の日本語は文字化けしてしまう!どうすればいいのか。
ちゃんと回答はあった。以下のページの最後に書いてある。
iphone – Non US characters in section headers for a UITableView – Stack Overflow
– (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName {
return sectionName;}
とやるだけでいい。

NSCharacterSetは日本語に対応しない?


皆さんはどうやって日本語文字の判定をしているのだろうか?
NSCharacterSetのalphanumericCharacterSetを使うと日本語もアルファベットの一種として判定してしまうようなのだが。
NSScannerでやっても漢字がアルファベットとマッチしてしまう。
唯一うまく行った方法はURLエンコードして、エラーでNULLが返ってくることで日本語だとわかる方法だった。でも、これは多分将来的に使えなくなる方法かもしれない。
なお、下記でinitialには文字列の頭文字(最初の1字)が入っていて、これが日本語かどうかを調べたいのである。
NSString* escapedUrlString = [initial stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
if (escapedUrlString != nil) {
if ([[NSScanner scannerWithString:initial] scanInt:nil]) {
initial = @”#”; // Number!
}
} else {
initial = @”*”; // Kaiji!
}
どうすればいい。もう二日も調べてわからない。

【追記】2011年8月21日:
iOS4.0以降なら正規表現が使えるようだ。以下でいける。
NSError* error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@”^[a-zA-Z0-9]*$” options:0 error:&error];
if ([regex numberOfMatchesInString:initial options:0 range:NSMakeRange(0, [initial length])] > 0) { }

UIViewでUIKeuInputをdelegateするにはcanBecomeFirstResponderが必要


まず、 UIKeyInputのデリゲート対象になるUIVeiwを何かひとつ決めなければならない。そして、このUIViewのなかで
– (BOOL)canBecomeFirstResponder
{
return YES;
}
する

UIKeyInputをはじめるタイミングで、[self becomeFirstResponder]する。例えばこのUIView内で、
– (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[self becomeFirstResponder];
}
とか。

こうしてはじめて、このUIViewの@ implementationのなかで、
– (BOOL)hasText{}
– (void)insertText:(NSString*)aString{}
– (void)deleteBackward{}
が使えるようになる。

canBecomeFirstResponderを知らないことと、何かdelegate先指定が必要だとばかり思い込んでどうやって指定するか調べまわって遠回りしてしまった。