僕のYak Shavingは終わらない

車輪の再発明をやめたらそこには壮大なYakの群れが

UITextViewに文字を挿入するときにスクロールしてしまうのを回避

もしかしたら基本なのかもしれませんがUITextViewであるテキストプログラム側で挿入したくなった時のお作法。
http://stackoverflow.com/questions/2792589/uitextview-insert-text-in-the-textview-text

- (void) insertString: (NSString *) insertingString intoTextView: (UITextView *) textView  
{  
    NSRange range = textView.selectedRange;  
    NSString * firstHalfString = [textView.text substringToIndex:range.location];  
    NSString * secondHalfString = [textView.text substringFromIndex: range.location];  
    textView.scrollEnabled = NO;  // turn off scrolling or you'll get dizzy ... I promise  

    textView.text = [NSString stringWithFormat: @"%@%@%@",  
      firstHalfString,  
      insertingString,  
      secondHalfString];  
    range.location += [insertingString length];  
    textView.selectedRange = range;  
    textView.scrollEnabled = YES;  // turn scrolling back on.  
}

↑は引用。
指定の挿入文句insertignStringと挿入したいUITextViewを指定して挿入処理をするメソッド。
手順をいうと、

  • 挿入する場所でtextViewの文字を前後に分割する
  • scrollEnabledをNOにしてスクロール不可にする(重要!
  • textView.textに挿入後の文字列を代入する(このときスクロール可能だと末尾までスクロールしてしまう
  • selectedRange(カーソル位置)を挿入文字列長の分だけ後ろにずらす
  • scrollEnabledをYESにしてスクロール可能にする(重要!

です。

最初scrollEnabledの存在に気づかずかなりはまりました。selectedRangeは適切に処理していたのである行数以内では正常に動作していたのに、行幅がある程度大きくなってくると↑↓ぐわんぐわんスクロールしまくって手に負えない始末。。。

selectedRangeさえ適切に指定していればセレクトした位置にスクロールしてくれるかと思ったらときと場合によってはうまく動かないんですね(時と場合によって・・・のために時間を食いました)。

スクロールが問題ならスクロールできないようにしてしまえばいい。
確かに、と。


このままでもいいんですけど自分は以下のようにスクリプトを組みました。

- (void) insertString: (NSString *) insertingString intoTextView: (UITextView *) textView  
{
    //  元のカーソル位置を取得
    NSRange range = textView.selectedRange;
    // 文字列取得
    NSMutableString *str = (NSMutableString *)textView.text;
    // stringWithFormatでもいいけどこっちの方がスマート
    [str insertString:insertingString atIndex:textSelectedLocation];
    // スクロール不可に
    textView.scrollEnabled = NO;
    // テキスト更新
    textView.text = str;
    // もうスクロールしないのでスクロール可に
    textView.scrollEnabled = YES;
    // 挿入分だけカーソル位置移動
    range.location += [insertingString length];  
    textView.selectedRange = range;
}

誰かの参考になれば。