はい。ただし、UILabel ではなく、sizeWithFont: を使用していません。
私は最近 Apple Developer Support と協力しましたが、どうやら sizeWithFont: は実際には近似値です。テキストが (1) 複数の行にまたがって折り返され、(2) 非ラテン文字 (中国語、アラビア語など) が含まれている場合、精度が低下します。どちらも sizeWithFont: でキャプチャされない行間隔の変更を引き起こします。したがって、100% の精度が必要な場合は、この方法に頼らないでください。
できることは次の 2 つです。
(1) UILabel の代わりに、編集不可の UITextView を使用します。これは、UITextInput プロトコル メソッドfirstRectForRange:をサポートします。これを使用して、必要な文字の四角形を取得できます。次のような方法を使用できます。
- (CGRect)rectOfCharacterAtIndex:(NSUInteger)characterIndex inTextView:(UITextView *)textView
{
// set the beginning position to the index of the character
UITextPosition *beginningPosition = [textView positionFromPosition:textView.beginningOfDocument offset:characterIndex];
// set the end position to the index of the character plus 1
UITextPosition *endPosition = [textView positionFromPosition:beginningPosition offset:1];
// get the text range between these two positions
UITextRange *characterTextRange = [textView textRangeFromPosition:beginningPosition toPosition:endPosition]];
// get the rect of the character
CGRect rectOfCharacter = [textView firstRectForRange:characterTextRange];
// return the rect, converted from the text input view (unless you want it to be relative the text input view)
return [textView convertRect:rectOfCharacter fromView:textView.textInputView];
}
これを使用するには (myTextView という名前の UITextView が既に画面上にあると仮定します)、次のようにします。
myTextView.text = @"Hello!";
CGRect rectOfOCharacter = [self rectOfCharacterAtIndex:4 inTextView:myTextView];
// do whatever you need with rectOfOCharacter
このメソッドは、 1文字の矩形を決定するためにのみ使用してください。この理由は、改行が発生した場合、firstRectForRange: は改行前の最初の行の rect のみを返すためです。
また、上記のメソッドを頻繁に使用する場合は、UITextView カテゴリとして追加することを検討してください。エラー処理を追加することを忘れないでください!
iOS 用 Text, Web, and Editing Programming Guide を読むと、firstRectForRange: が「フードの下」でどのように機能するかについて詳しく知ることができます。
(2) UIView をサブクラス化し、Core Text を使用して文字列をレンダリングすることにより、独自の UILabel を作成します。レンダリングを行っているので、文字の位置を取得できます。このアプローチは大変な作業であり、本当に必要な場合にのみ価値があります (もちろん、私はあなたのアプリの他のニーズを知りません)。これがどのように機能するかわからない場合は、最初のアプローチを使用することをお勧めします。