0

CoreText を使用してテキストのハイライトを描画するアプリがあります。それを使用して行の文字数を取得しようとすると、CTLineGetStringRange通常は実際よりも大きな数値が得られることを除いて、うまく機能します。たとえば、156 文字を含む行では、範囲の長さは 164 でしたCTLineGetGlyphCount。同じ数値が返されました。

なぜこれが起こるのか誰にも分かりますか?フレームセッターのNSAttributedString作成に使用する は、私の とまったく同じフォントを使用していUITextViewます。

これが私のコードです:

// Build the attributed string from our text data and string attribute data
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.text attributes:self.attributes];    

// Create the Core Text framesetter using the attributed string
_framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedString);
// Create the Core Text frame using our current view rect bounds
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.bounds];
_frame =  CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), path.CGPath, NULL);

NSArray *lines = (__bridge NSArray *) CTFrameGetLines(_frame);
for (int i = 0; i < lines.count; i++) {
    CTLineRef line = (__bridge CTLineRef) [lines objectAtIndex:i];
    CFRange lineRange = CTLineGetStringRange(line);
    NSLog(@"lineRange: %ld, %ld", lineRange.location, lineRange.length);
    CFIndex glyphCount = CTLineGetGlyphCount(line);
    NSLog(@"glyphCount: %ld", glyphCount);
}

私のクラスは、 のサブクラスのUIViewインスタンスにサブビューとして追加されるサブクラスですUITextView

編集: これは私がテストしている文字列の例です:

textView.text = @"Marvel's The Avengers is a 2012 American superhero film produced by Marvel Studios and distributed by Walt Disney Pictures, based on the Marvel Comics superhero team of the same name.";

この場合、最初の行には
「Marvel's The Avengers is a 2012 American superhero film is a 2012 american superhero film by Marvel Studios, Produced by Walt Disney Pictures, based on the 137 character length. しかし、長さ 144 の線の範囲が得られます。

ただし、次のテキストで試したところ、結果は異なりました。

textView.text = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";

最初の行には
、長さ 142 の「Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut Labore et dolore magna aliqua. Ut enim ad minim」が含まれています。

次に、さらにいくつかのテキストを試しました。

テキスト: 「アスガルド人のロキは、チタウリとして知られるエイリアン種族のリーダーであるアザーに遭遇します。アザーは、未知の可能性の強力なエネルギー源であるテッセラクトを回収する代わりに、地球を征服できるチタウリ軍をロキに約束します。 ."
結果:「アスガルドのロキは、チタウリとして知られるエイリアンの種族のリーダーであるアザーに遭遇します。長さ 145 の強力なテッセラクトを取得することと引き換えに。
ライン レンジの長さ: 145

テキスト: "スタークとロジャースは、単に彼らを打ち負かすだけではロキにとって十分ではないことを認識しています。彼は公に彼らを圧倒し、自分が地球の支配者であることを証明する必要があります。"
結果:「スタークとロジャースは、単に彼らを打ち負かすだけではロキにとって十分ではないことを認識しています。彼は自分が統治者であることを証明するために公に彼らを圧倒する必要があります」 と長さ 146.
ライン レンジの長さ: 149

ご覧のとおり、正しい場合もあれば、正しくない場合もあります。説明が見つかりません。

4

1 に答える 1

1

この回答で与えられたヒントに基づいて問題を解決しました。

それをUITextView継承しUIScrollViewているため、すべてのエッジに8ピクセルのインセットがあるようです。これは、私の内部UIViewのテキスト用のスペースが私よりも 16 ピクセル広いUITextViewことを意味し、その違いは、新しい行に移動する前に 1 つ多くの単語を収めることができ、行の文字数が間違っていたことを意味していました。

したがって、ビューの幅から 16 ピクセルを差し引くと、問題が解決しました。

ただし、これは私のソリューションの一部にすぎません。他の部分は、コアテキストの属性付き文字列からカーニングと合字を削除することでした:

CFAttributedStringSetAttribute(string, textRange, kCTKernAttributeName, (__bridge CFTypeRef)([NSNumber numberWithFloat:0.0]));
CFAttributedStringSetAttribute(string, textRange, kCTLigatureAttributeName, (__bridge CFTypeRef)([NSNumber numberWithInt:0]));

これで、ラインが完全に一致します。

于 2012-08-13T12:14:01.157 に答える