保留对 CTFramesetter 的引用以加快核心文本绘制速度

发布于 2024-12-17 07:57:03 字数 2207 浏览 2 评论 0原文

我希望在大量 UITableViewCell 上渲染文本。 文本在 UITableViewCells drawRect:(CGRect)rect 方法中呈现。

每个单元格包含不同数量的行,并且文本具有粗细和颜色等属性。

中 - (void) tableview:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath; 我将 attributeString 传递给 tableViewCell,这是我在构建模型时预先创建的。 我附加了一些代码,显示了我的drawRect中发生的事情的要点。

我一直在阅读(文档、博客等),CTFrameSetter 是创建成本最高的对象。这是有道理的,因为这是计算字形和运行的所有计算的。 我现在的问题是,我也可以预先制作这个并将其传递到我的手机吗 在 cellForRowAtIndexPath 上,它是否可能对速度产生积极影响?

- (void) drawRect:(CGRect)rect
{   
/* These are pre-populated and the attributedString is passed to the cell at run time

    NSDictionary *stringAttributeDict = [NSDictionary dictionaryWithObjectsAndKeys:
                         (id)fontRef, (NSString*)kCTFontAttributeName, 
                         (id)[[UIColor blueColor] CGColor], (NSString*)(kCTForegroundColorAttributeName), nil]];
    NSDictionary *firstPartAttributeDict = [NSDictionary dictionaryWithObjectsAndKeys:
                          (id)fontRef, (NSString*)kCTFontAttributeName, 
                          (id)[[UIColor greenColor] CGColor], (NSString*)(kCTForegroundColorAttributeName), nil]];

    [attributedString addAttributes:stringAttributeDict range:NSMakeRange(0, [attributedString.string length])];
    [attributedString addAttributes:firstPartAttributeDict range:NSMakeRange(0, 5)];

*/
    rect = CGRectInset(rect, 5.0, 5.0);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Flip the coordinate system
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    //Make a path to render the text in
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, rect);

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
    CTFrameRef theFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attributedString length]), path, NULL);
    CFRelease(framesetter);
    CFRelease(path);

    //Draw the text:
    CTFrameDraw(theFrame, context);
    CFRelease(theFrame);
}

I wish to render text on a large amount of UITableViewCell's.
The text is rendered in a UITableViewCells drawRect:(CGRect)rect method.

Each cell contains a different number of lines and the text has attributes like weight and color.

In - (void) tableview:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath;
I pass the tableViewCell the attributedString, which I pre made when building my model.
I attached some code that shows the gist of what goes on in my drawRect.

I keep reading (documentation, blogs etc.) that the CTFrameSetter is the most expensive object to create. This makes sense as this is were all the calculations for the glyphs and runs are calculated. My question now is, can I pre make this as well and pass it to my cell
on cellForRowAtIndexPath and is it likely to have a positive effect on speed?

- (void) drawRect:(CGRect)rect
{   
/* These are pre-populated and the attributedString is passed to the cell at run time

    NSDictionary *stringAttributeDict = [NSDictionary dictionaryWithObjectsAndKeys:
                         (id)fontRef, (NSString*)kCTFontAttributeName, 
                         (id)[[UIColor blueColor] CGColor], (NSString*)(kCTForegroundColorAttributeName), nil]];
    NSDictionary *firstPartAttributeDict = [NSDictionary dictionaryWithObjectsAndKeys:
                          (id)fontRef, (NSString*)kCTFontAttributeName, 
                          (id)[[UIColor greenColor] CGColor], (NSString*)(kCTForegroundColorAttributeName), nil]];

    [attributedString addAttributes:stringAttributeDict range:NSMakeRange(0, [attributedString.string length])];
    [attributedString addAttributes:firstPartAttributeDict range:NSMakeRange(0, 5)];

*/
    rect = CGRectInset(rect, 5.0, 5.0);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Flip the coordinate system
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    //Make a path to render the text in
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, rect);

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
    CTFrameRef theFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attributedString length]), path, NULL);
    CFRelease(framesetter);
    CFRelease(path);

    //Draw the text:
    CTFrameDraw(theFrame, context);
    CFRelease(theFrame);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

终弃我 2024-12-24 07:57:03

是的,您应该能够保留它并在单元之间共享它。我为单个视图内的多个文本块保留了持久的 CTFramesetterRef ,我不明白为什么将它用于表视图中的多个单元格会有什么不同。

Yes, you should be able to keep it around and share it between cells. I have kept a persistent CTFramesetterRef around for multiple text blocks inside of a single view, I can't see why using it for multiple cells in a tableview would be any different.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文