Подтвердить что ты не робот

Как разделить длинный NSString на страницы

У меня длинный NSString, который я хочу отобразить на нескольких страницах.

Но для этого мне нужно выяснить, сколько текста будет действительно соответствовать на странице.

[NSString sizeWithFont:...] Недостаточно, он просто скажет мне, подходит ли текст в прямоугольнике или нет, если его нет, он будет молча усекать строку, но он не скажет мне, где он усечен!

Мне нужно знать первое слово, которое не помещается на странице, поэтому я могу разбить строку и нарисовать ее на следующей странице. (и повторить)

Есть идеи, как это решить?

Единственная идея, которую я до сих пор знаю, - это неоднократно вызывать sizeWithFont: constrainedToSize: вокруг точки в строке, где я предполагаю, что разрыв страницы будет, и проанализировать полученный результат, но он кажется громоздким и медленным, и я чувствую себя У меня могут быть дополнительные проблемы, получая его на 100% точным... (из-за descenders и еще чего-то.)

ofc, он должен быть доступен в общедоступном SDK для iOS

Ответ:

Фу, это была какая-то волосатая документация. Вот моя законченная функция в качестве примера, возможно, это поможет кому-то, поскольку там не так много конкретных текстовых примеров для 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 или строковыми чертежами! Вы должны использовать его только с Core Text, например, создавая CTFrame и рисуя это. Тонкие различия в таких вещах, как кернинг, не позволяют комбинировать функции Core Text с UIKit.

Кроме того, обратите внимание, что возвращаемый размер был признан ошибочным.

4b9b3361

Ответ 1

Вы должны заглянуть в CoreText, доступный с iOS 3.2. Документы довольно сложны и здесь можно найти здесь. В основном вы создаете CTFramesetter и вызываете CTFramesetterSuggestFrameSizeWithConstraints. Затем вы найдете диапазон текста, который соответствует заданному CGSize.