それほど単純ではありません。使用:
CGSize sizeOfString = [string sizeWithFont:self.aTextView.font constrainedToSize:self.aTextView.frame.size];
指定された文字列の CGSize を取得できます。ただし、文字列全体を指定すると、UITextView のサイズ (つまり、右下隅) と同じサイズになります。
各 UITextField の最後の行でこのメソッドを使用する必要があります...これは難しい部分です。ワードラップはCoreText、UITextView、またはUILabelによって行われ、単一行、位置などに関する情報は提供されません.
同様のことをして自分で計算する必要があります (コードはあまりきれいではありません。理解に問題がある場合は、後でお手伝いします)。
NSAttributedString* text = self.aTextView.attributedText;
CTFramesetterRef fs =
CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)text);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,self.aTextView.frame.size.width - 16,100000)); // why the -16? the frame should be the REAL TEXT FRAME, not the UITextView frame. If you look, there is a space between the view margin and the text. This is the baseline. Probably there is a method to calculate it programatically, but I can't check now. In my case it seems like 8px (*2)
CTFrameRef f = CTFramesetterCreateFrame(fs, CFRangeMake(0, 0), path, NULL);
CTFrameDraw(f, NULL);
NSRange lastRange;
NSArray* lines = (__bridge NSArray*)CTFrameGetLines(f);
id lastLineInArray = [lines lastObject];
CTLineRef theLine = (__bridge CTLineRef)lastLineInArray;
CFRange range = CTLineGetStringRange(theLine);
lastRange.length = range.length;
lastRange.location = range.location - 1;
NSLog(@"%ld %ld", range.location, range.length);
CGPathRelease(path);
CFRelease(f);
CFRelease(fs);
// this is the last line
NSString *lastLine = [self.aTextView.text substringWithRange:lastRange];
これで、次を使用できます。
CGSize sizeOfString = [lastLine sizeWithFont:self.aTextView.font constraintToSize:self.aTextView.frame.size];
文字列の幅と高さを取得してから、ボタンの最終的な位置を取得します (y 位置の場合: 行配列カウントから取得した行数 * 文字列の高さ)
編集: UITextView の左スペースに関するコメント (この行に -16 がある理由)
CGPathAddRect(path, NULL, CGRectMake(0,0,self.aTextView.frame.size.width - 16,100000));
これは、テキストが実際には UITextView 内にあるのではなく、そのサブビューの 1 つである、インセットを追加する UIWebDocumentView (プライベート クラス) 内にあるために発生します。いくつかの検索の後、CGPathAddRect() 関数に正しい四角形を渡すために必要な、このインセットの値を (合法的に) 取得する方法が見つかりません。常に8ptであることを確認するためにいくつかのテストを行うことができます:-)またはそのコンテンツインセットを持たないUILabelに切り替えます