我已经为此工作了好几天,几乎可以正常工作。我遇到的问题是,当我更新 UIView 内容(通过将文本字符串加倍)时, super View (UIScrollView) 显示更新内容的两倍大小。
基本上,我在 IB 中创建了一个 UIViewController,它附加了一个 UIScrollView。 UIScrollView 以编程方式创建它的子 UIView。 UIView 应该显示一个小的“正在加载...”文本(通过 Core Text),然后该文本会更改为从 URL 加载的真实内容。
在我的测试中,我用比 UIScrollView 大 2 行的段落替换了“正在加载...”文本。它可以正确显示并完美滚动。
当 URL 完成加载时,我将段落替换为完全相同的段落两次(字符串长度加倍)。然后我在子 UIView 上执行 setNeedDisplay。 UIView(在它的 drawRect 中使用相同的代码)获取新边界、绘制文本并更新父级 (UIScrollView) 的 contentSize。
当模拟器上的屏幕更新时,我的是显示的内容,但是高度加倍,导致第二段文字被截断。
然后在 child 的 drawRect 结束时,我有 NSLog'd parent 的框架、边界、contentSize 等,以及 child 的框架和边界。在我看来一切都是正确的... child 的框架和边界是原来高度的两倍, parent 的 contentSize 是原来的两倍,框架和边界保持不变。
所以,那里一定有另一层影响了绘图,但我就是找不到它。欢迎提出任何建议。
这是我的内容 View 的 drawRect():
- (void)drawRect:(CGRect)rect
{
CTTextAlignment paragraphAlignment = kCTLeftTextAlignment;
CTParagraphStyleSetting setting[1] =
{
{ kCTParagraphStyleSpecifierAlignment, sizeof(paragraphAlignment), ¶graphAlignment },
};
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);
}
最佳答案
好的,看来问题与从 drawRect 函数内部更改 View 的大小有关。
当我将 framesetter 初始化提取到它自己的函数中,然后让该函数调用 setNeedDisplay 时,这似乎解决了我遇到的问题。
-(void)updateText:(NSString*)textStr
{
if (textStr == longText) { return; }
longText = textStr;
CTTextAlignment paragraphAlignment = kCTLeftTextAlignment;
CTParagraphStyleSetting setting[1] =
{
{ kCTParagraphStyleSpecifierAlignment, sizeof(paragraphAlignment), ¶graphAlignment },
};
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);
}
关于iOS UIScrollView/UIView 以双倍大小显示更新的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6496603/