DTCoreText项目使用浅析 (2)

前一篇提到生成NSAttributedString,接下面就是如何将NSAttributedString展示出来

DTAttributedTextContentView的主要结构

@interface DTAttributedTextContentView : UIView 
{
    NSAttributedString *_attributedString;
    DTCoreTextLayoutFrame *_layoutFrame;
    
    UIEdgeInsets edgeInsets;
    
    NSMutableDictionary *customViewsForAttachmentsIndex;
}

- (id)initWithAttributedString:(NSAttributedString *)attributedString width:(CGFloat)width;

- (void)resetWithLayouterWithFrame:(DTCoreTextLayouter *)layouter layoutFrame: (DTCoreTextLayoutFrame *)layoutFrame frame:(CGRect)frame;

- (void)layoutSubviewsInRect:(CGRect)rect;
- (void)relayoutText;
- (void)removeAllCustomViews;
- (void)removeAllCustomViewsForLinks;

- (CGSize)attributedStringSizeThatFits:(CGFloat)width;
- (CGSize)suggestedFrameSizeToFitEntireStringConstraintedToWidth:(CGFloat)width; // obeys the edge insets

// properties are overwritten with locking to avoid problem with async drawing
@property (atomic, strong) DTCoreTextLayouter *layouter;
@property (atomic, strong) DTCoreTextLayoutFrame *layoutFrame;

@property (nonatomic, strong) NSMutableSet *customViews;

其中有两个布局相关的元素:

@property (atomic, strong) DTCoreTextLayouter *layouter;
@property (atomic, strong) DTCoreTextLayoutFrame *layoutFrame;

 

其中DTCoreTextLayoutFrame有个重要的方法叫做

 

- (void)_buildLines

 

这里就开始根据attributedString做各种段落和行数的设置了,局限于Coretext的知识,这里我无法给出一个详细的说明

 

DTAttributedTextContentView重载了layoutSubviews和实现了- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

        NSAttributedString *layoutString = [theLayoutFrame attributedStringFragment];
        NSArray *lines;
        if (CGRectIsInfinite(rect))
        {
            lines = [theLayoutFrame lines];
        }
        else
        {
            lines = [theLayoutFrame linesVisibleInRect:rect];
        }

接着遍历line

for (DTCoreTextLayoutLine *oneLine in lines)
        {
            NSRange lineRange = [oneLine stringRange];
            
            NSUInteger skipRunsBeforeLocation = 0;
            
            for (DTCoreTextGlyphRun *oneRun in oneLine.glyphRuns)

针对每个单元,查找link和attachment的属性,这里还对attachment的view做了缓存优化

if (_delegateFlags.delegateSupportsCustomViewsForAttachments)
                                {
                                    newCustomAttachmentView = [_delegate attributedTextContentView:self viewForAttachment:attachment frame:frameForSubview];
                                }
                                else if (_delegateFlags.delegateSupportsGenericCustomViews)
                                {
                                    NSAttributedString *string = [layoutString attributedSubstringFromRange:runRange]; 
                                    newCustomAttachmentView = [_delegate attributedTextContentView:self viewForAttributedString:string frame:frameForSubview];
                                }

委托生成对应的custom view, 这里可以做些图文混排的工作,比如图片、链接等

这里补充下,这里custom view生成时,可以动态调整相关高度,也就是说不用去更新nsattributedstring,动态加载图片就是这样处理的。

等custom view生成完毕后,开始调用

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

DTCoreTextLayoutFrame *theLayoutFrame = self.layoutFrame;
    
    // need to prevent updating of string and drawing at the same time
    SYNCHRONIZE_START(selfLock)
    {
        [theLayoutFrame drawInContext:ctx drawImages:shouldDrawImages];
        
        if (_delegateFlags.delegateSupportsNotificationAfterDrawing)
        {
            [_delegate attributedTextContentView:self didDrawLayoutFrame:theLayoutFrame inContext:ctx];
        }
    }
    SYNCHRONIZE_END(selfLock)

DTCoreTextLayoutFrame这个方法负责将构造出来的DTCoreTextLayoutLine数组,通过CoreText绘制到图形上下文中,还利用CoreGraphics画线、背景等一系列效果;这里也可以定制部分特殊效果功能。

 

这样DTCoreText的基本流程就完成了,里面很多细节没有涉及,和CoreText相关的功能还待学习。

 

posted @ 2013-12-16 23:10  wtndcs  阅读(1590)  评论(1编辑  收藏  举报