私はUILabelをサブクラス化しており、drawRectを使用する代わりに、テキストをバックグラウンドでUIImageにレンダリングしています。コードは次のとおりです。
- (UIImage *)imageForText
{
UIGraphicsBeginImageContextWithOptions(self.frameSize, NO, 0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGAffineTransform transform = [self _transformForCoreText];
CGContextConcatCTM(ctx, transform);
if (nil == self.textFrame) {
CFAttributedStringRef attributedString = (__bridge CFAttributedStringRef)attributedStringWithLinks;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attributedString);
CGMutablePathRef path = CGPathCreateMutable();
// We must tranform the path rectangle in order to draw the text correctly for bottom/middle
// vertical alignment modes.
CGPathAddRect(path, &transform, rect);
if (nil != self.shadowColor) {
CGContextSetShadowWithColor(ctx, self.shadowOffset, self.shadowBlur, self.shadowColor.CGColor);
}
self.textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
}
// Draw the tapped link's highlight.
if ((nil != self.touchedLink || nil != self.actionSheetLink) && nil != self.highlightedLinkBackgroundColor) {
[self.highlightedLinkBackgroundColor setFill];
NSRange linkRange = nil != self.touchedLink ? self.touchedLink.range : self.actionSheetLink.range;
CFArrayRef lines = CTFrameGetLines(self.textFrame);
CFIndex count = CFArrayGetCount(lines);
CGPoint lineOrigins[count];
CTFrameGetLineOrigins(self.textFrame, CFRangeMake(0, 0), lineOrigins);
for (CFIndex i = 0; i < count; i++) {
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CFRange stringRange = CTLineGetStringRange(line);
NSRange lineRange = NSMakeRange(stringRange.location, stringRange.length);
NSRange intersectedRange = NSIntersectionRange(lineRange, linkRange);
if (intersectedRange.length == 0) {
continue;
}
CGRect highlightRect = [self _rectForRange:linkRange inLine:line lineOrigin:lineOrigins[i]];
if (!CGRectIsEmpty(highlightRect)) {
CGFloat pi = (CGFloat)M_PI;
CGFloat radius = 5.0f;
CGContextMoveToPoint(ctx, highlightRect.origin.x, highlightRect.origin.y + radius);
CGContextAddLineToPoint(ctx, highlightRect.origin.x, highlightRect.origin.y + highlightRect.size.height - radius);
CGContextAddArc(ctx, highlightRect.origin.x + radius, highlightRect.origin.y + highlightRect.size.height - radius,
radius, pi, pi / 2.0f, 1.0f);
CGContextAddLineToPoint(ctx, highlightRect.origin.x + highlightRect.size.width - radius,
highlightRect.origin.y + highlightRect.size.height);
CGContextAddArc(ctx, highlightRect.origin.x + highlightRect.size.width - radius,
highlightRect.origin.y + highlightRect.size.height - radius, radius, pi / 2, 0.0f, 1.0f);
CGContextAddLineToPoint(ctx, highlightRect.origin.x + highlightRect.size.width, highlightRect.origin.y + radius);
CGContextAddArc(ctx, highlightRect.origin.x + highlightRect.size.width - radius, highlightRect.origin.y + radius,
radius, 0.0f, -pi / 2.0f, 1.0f);
CGContextAddLineToPoint(ctx, highlightRect.origin.x + radius, highlightRect.origin.y);
CGContextAddArc(ctx, highlightRect.origin.x + radius, highlightRect.origin.y + radius, radius,
-pi / 2, pi, 1);
CGContextFillPath(ctx);
}
}
CTFrameDraw(self.textFrame, ctx);
CGContextRestoreGState(ctx);
self.renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return self.renderedImage;
}
これが、Instrumentsの割り当てツールで得ているもののスナップショットです。
これを深く掘り下げる方法はわかりませんが、画像はリリースされておらず、メモリに保持されているようです。私が持っているUIScrollViewをスクロールして、このメソッドを呼び出すにつれて、画像は増えていきます。何か案は?上記の私のコードに何か問題がありますか?リークを使用してプロファイルを作成しましたが、リークの兆候は見つかりませんでした...
編集:
imageForTextの呼び出し方法に関するコードを追加しました。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[self parseTagsInComment];
[self.commentsText_ setLinkColor:self.textColor_];
[weakSelf.commentsText_ imageForText];
UIImage *renderedImage = [weakSelf.commentsText_ imageForText];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.commentTextImageView_ setImage:renderedImage];
[weakSelf.commentTextImageView_ setAlpha:0.0];
[UIView animateWithDuration:0.3 animations:^{
[weakSelf.commentTextImageView_ setAlpha:1.0];
}];
});
[pool release];
});
私はそれをするだけでそれを呼んでみました:
[self.commentsText_ imageForText];
それでもメモリは急上昇します