iOS UIScrollView / UIView显示双倍大小的更新内容

时间:2011-06-27 17:30:31

标签: ios uiview uiscrollview

我已经在这方面工作了好几天,而且我几乎都有工作。我遇到的问题是,当我更新UIView内容时(通过加倍文本字符串),superview(UIScrollView)会显示双倍大小的更新内容。

基本上,我在IB中创建了一个附加了UIScrollView的UIViewController。 UIScrollView以编程方式创建它的子UIView。 UIView应该显示一个小的“Loading ...”文本(通过Core Text),然后更改为从URL加载的真实内容。

在我的测试中,我用一个比UIScrollView大2行的段落替换了“Loading ...”文本。它显示正确并滚动完美。

当URL完成加载时,我用完全相同的段落替换段落两次(字符串长度的两倍)。然后我在孩子UIView上做一个setNeedDisplay。 UIView(在其drawRect中使用相同的代码)获取新边界,绘制文本,并更新父级(UIScrollView)contentSize。

当模拟器上的屏幕更新时,我所拥有的是显示的内容,但是高度加倍,导致第二段文本被截断。

在孩子的drawRect的最后,我有NSLog'd父母的框架,边界,contentSize等,以及孩子的框架&界限。对我来说一切看起来都是正确的...孩子的框架和边界的高度是原来的两倍,父母的contentSize是框架的两倍,边界保持不变。

所以,那里必须有另一层影响绘图的地方,但我根本找不到它。欢迎任何建议。

这是我的内容视图的drawRect():

- (void)drawRect:(CGRect)rect
{    
    CTTextAlignment paragraphAlignment  = kCTLeftTextAlignment;
    CTParagraphStyleSetting setting[1] = 
    {
        {   kCTParagraphStyleSpecifierAlignment, sizeof(paragraphAlignment), &paragraphAlignment },
    };

    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(setting, 1);

    NSMutableAttributedString* string = [[[NSMutableAttributedString alloc] initWithString:longText attributes:
                                       [NSDictionary dictionaryWithObjectsAndKeys:(id)helvetica, (NSString*)kCTFontAttributeName,
                                        paragraphStyle, (NSString*)kCTParagraphStyleAttributeName, nil]] autorelease];

    CFRelease(paragraphStyle);    

    [string addAttribute:(id)kCTFontAttributeName
                   value:(id)helvetica
                   range:NSMakeRange(0, [string length])];

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);

    CGSize  size = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
                                                                CFRangeMake(0, 0),
                                                                NULL,
                                                                CGSizeMake(rect.size.width - 3, CGFLOAT_MAX),
                                                                NULL);

    [self setFrame:CGRectMake(0, 0, (int)(size.width + 0.5), (int)(size.height + 0.5))];

    MyContentScroller*   scroller = (MyContentScroller*)self.superview;
    [scroller setContentSize:self.bounds.size];

    CGMutablePathRef columnPath = CGPathCreateMutable();
    CGRect bounds = CGRectMake(2, 2, self.bounds.size.width - 4, self.bounds.size.height);
    CGPathAddRect(columnPath, NULL, bounds);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, 
                                                CFRangeMake(0, 0),
                                                columnPath, NULL);
    CGPathRelease(columnPath);
    CFRelease(framesetter);

    CGContextRef    context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CTFrameDraw(frame, context);
    CFRelease(frame);

    CGContextRestoreGState(context);
}

1 个答案:

答案 0 :(得分:1)

好的,似乎问题与从drawRect函数内部更改视图的大小有关。

当我将framesetter初始化拉出到它自己的函数中时,然后让该函数调用setNeedDisplay,这似乎解决了我遇到的问题。

-(void)updateText:(NSString*)textStr
{
    if (textStr == longText)   {   return; }

    longText = textStr;

    CTTextAlignment paragraphAlignment  = kCTLeftTextAlignment;
    CTParagraphStyleSetting setting[1] = 
    {
        {   kCTParagraphStyleSpecifierAlignment, sizeof(paragraphAlignment), &paragraphAlignment },
    };

    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(setting, 1);

    NSMutableAttributedString* string = [[[NSMutableAttributedString alloc] initWithString:longText attributes:
                                          [NSDictionary dictionaryWithObjectsAndKeys:(id)helvetica, (NSString*)kCTFontAttributeName,
                                           paragraphStyle, (NSString*)kCTParagraphStyleAttributeName, nil]] autorelease];

    CFRelease(paragraphStyle);    

    [string addAttribute:(id)kCTFontAttributeName
                   value:(id)helvetica
                   range:NSMakeRange(0, [string length])];

    if (framesetter)    {   CFRelease(framesetter); }

    framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);

    CGSize  size = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
                                                                CFRangeMake(0, 0),
                                                                NULL,
                                                                CGSizeMake(self.bounds.size.width - 4, CGFLOAT_MAX),
                                                                NULL);

    [self setFrame:CGRectMake(0, 0, (int)(size.width + 0.5), (int)(size.height + 0.5))];

    MyContentScroller*   scroller = (MyContentScroller*)self.superview;
    [scroller setContentSize:self.bounds.size];

    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{    
    if (!framesetter)   {   return; }

    CGMutablePathRef columnPath = CGPathCreateMutable();
    CGRect bounds = CGRectMake(2, 2, self.bounds.size.width - 4, self.bounds.size.height);
    CGPathAddRect(columnPath, NULL, bounds);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, 
                                                CFRangeMake(0, 0),
                                                columnPath, NULL);
    CGPathRelease(columnPath);

    CGContextRef    context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CTFrameDraw(frame, context);
//    CFRelease(frame);     // This line causes a crash!

    CGContextRestoreGState(context);
}