Что-то вроде этой процедуры для визуализации текста:
- (CFRange)renderTextRange:(CFRange)currentRange andFrameSetter:(CTFramesetterRef)frameSetter intoRect:(CGRect)frameRect {
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
CTFrameRef frameRef = CTFramesetterCreateFrame(frameSetter, currentRange, framePath, NULL);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
CGContextTranslateCTM(currentContext, 0, 792);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CTFrameDraw(frameRef, currentContext);
CGContextRestoreGState(currentContext);
CGPathRelease(framePath);
currentRange = CTFrameGetVisibleStringRange(frameRef);
currentRange.location += currentRange.length;
currentRange.length = 0;
CFRelease(frameRef);
return currentRange;
}
И следующий фрагмент кода, который вызывает его, при условии, что у вас есть контекст, все шрифты и т. Д., Созданные в соответствующих переменных. Следующий цикл просто строит текст построчно в NSMutableAttributedString
, который вы затем можете визуализировать:
CTFontRef splainFont = CTFontCreateWithName(CFSTR("Helvetica"), 10.0f, NULL);
CGFloat margin = 32.0f;
CGFloat sink = 8.0f;
NSMutableAttributedString *mainAttributedString = [[NSMutableAttributedString alloc] init];
NSMutableString *mainString = [[NSMutableString alloc] init];
// Ingredients is an NSArray of NSDictionaries
// But yours could be anything, or just an array of text.
for (Ingredient *ingredient in ingredients) {
NSString *ingredientText = [NSString stringWithFormat:@"%@\t%@
\n",ingredient.amount,ingredient.name];
[mainString appendString:ingredientText];
NSMutableAttributedString *ingredientAttributedText =
[[NSMutableAttributedString alloc] initWithString:ingredientText];
[ingredientAttributedText addAttribute:(NSString *)(kCTFontAttributeName)
value:(id)splainFont
range:NSMakeRange(0, [ingredientText length])];
[mainAttributedString appendAttributedString:ingredientAttributedText];
[ingredientAttributedText release];
}
Теперь у вас есть массив, записанный с новыми строками в один NSMutableAttributedString
, который вы можете отрендерить, в зависимости от вашего текста вы можете рендерить его в цикле, пока отображаемое местоположение не будет соответствовать длине вашего текста. Что-то вроде:
// Render Main text.
CTFramesetterRef mainSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)mainAttributedString);
currentRange = [KookaDIS renderTextRange:currentRange
andFrameSetter:mainSetter
intoRect:pageRect];
// If not finished create new page and loop until we are.
while (!done) {
UIGraphicsBeginPDFPageWithInfo(pageRect, nil);
currentRange = [self renderTextRange:currentRange
andFrameSetter:mainSetter
intoRect:pageRect];
if (currentRange.location >= [mainString length]) {
done = TRUE;
}
}
Приведенный выше код потребует некоторой адаптации, я уверен, что он взломан из моего собственного проекта, поэтому некоторые переменные (например, установщик фреймов) не существуют, и вам необходимо закрыть контекст PDF и переменные выпуска и т. д. Обратите внимание, как mainString используется, чтобы определить, когда текст был обработан.
Он должен дать достаточно четкое указание на то, как обвести массив или любую другую группу, чтобы сделать произвольную длину текста в документе.
Небольшие изменения в цикле while и рендеринге перед его вводом позволят вам выводить текст также в несколько столбцов.