長い NSString をページに分割する方法
質問
数ページにわたって表示したい長い NSString があります。
ただし、これを行うには、ページに実際に収まるテキストの量を調べる必要があります。
[NSString sizeWithFont:...] だけでは十分ではありません。テキストが四角形に収まるかどうかを知らせてくれるだけです。収まらない場合は、黙って文字列を切り詰めますが、どこで切り詰められたのかは教えてくれません。
文字列を分割してその部分を次のページに描画できるように、ページに収まらない最初の単語を知る必要があります。(そして繰り返します)
これを解決する方法はありますか?
これまでのところ私自身の唯一のアイデアは、sizeWithFont:constrainedToSize: を繰り返し呼び出すことです。文字列内の改ページ位置付近で、結果の四角形を分析しますが、面倒で時間がかかり、100% 正確にするにはさらに問題が発生する可能性があると感じています...(ディセンダーなどのせいで。)
ofc、パブリック iOS SDK で利用できる必要があります
答え:
ふーん、それは毛深いドキュメントでした。ここに私の完成した関数を例として示します。iPhone 固有のコアテキストの例はあまりないので、おそらく誰かの役に立つでしょう。
+ (NSArray*) findPageSplits:(NSString*)string size:(CGSize)size font:(UIFont*)font;
{
NSMutableArray* result = [[NSMutableArray alloc] initWithCapacity:32];
CTFontRef fnt = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize,NULL);
CFAttributedStringRef str = CFAttributedStringCreate(kCFAllocatorDefault,
(CFStringRef)string,
(CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(id)fnt,kCTFontAttributeName,nil]);
CTFramesetterRef fs = CTFramesetterCreateWithAttributedString(str);
CFRange r = {0,0};
CFRange res = {0,0};
NSInteger str_len = [string length];
do {
CTFramesetterSuggestFrameSizeWithConstraints(fs,r, NULL, size, &res);
r.location += res.length;
[result addObject:[NSNumber numberWithInt:res.length]];
} while(r.location < str_len);
// NSLog(@"%@",result);
CFRelease(fs);
CFRelease(str);
CFRelease(fnt);
return result;
}
重要な注意点:
返された範囲やサイズを UIKit クラスや文字列描画関数で使用することはできません。これは、CTFrame を作成して描画するなど、Core Text でのみ使用する必要があります。カーニングなどの微妙な違いにより、Core Text 機能と UIKit を組み合わせることができなくなります。
また、返されたサイズにはバグがあることが判明していることに注意してください。
解決
あなたは、iOS 3.2以降で利用可能、CoreTextになっているはずです。ドキュメントがかなり複雑で、ここで見つけることができますに。基本的にはCTFramesetterとコールCTFramesetterSuggestFrameSizeWithConstraintsを作成します。あなたは、テキストの範囲を見つけること与えCGSize内に収まるます。