我创建了一个UIView类,可以轻松绘制而无需创建UIView的子类。 问题是,当我关闭应用程序并重新打开时(通常在低内存条件下),UIView绘图消失了。
我向您展示了该类别的代码:
的UIView + DrawBlock.h
#import <UIKit/UIKit.h>
// Blocks
typedef void(^DrawBlock)(CGContextRef context, CGRect drawFrame);
typedef void(^CompletionBlock)(UIView *view);
@interface UIView (DrawBlock)
- (void)drawInside:(DrawBlock)block withResult:(CompletionBlock)completion;
@end
的UIView + DrawBlock.m
#import "UIView+DrawBlock.h"
#pragma mark - Auxiliar UIView
@interface DrawingView : UIView
@property (strong, nonatomic) DrawBlock drawBlock;
- (void)setDrawRectBlock:(DrawBlock)block;
@end
@implementation DrawingView
- (void)setDrawRectBlock:(DrawBlock)block {
_drawBlock = block;
if (_drawBlock) {
[self setNeedsDisplay];
}
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
if (_drawBlock) {
_drawBlock(context, rect);
_drawBlock = nil;
}
}
@end
#pragma mark - Category
@implementation UIView (DrawBlock)
- (void)drawInside:(DrawBlock)block withResult:(CompletionBlock)completion {
if (block) {
DrawingView *drawView = [[DrawingView alloc] init];
drawView.translatesAutoresizingMaskIntoConstraints = NO;
drawView.userInteractionEnabled = NO;
drawView.backgroundColor = [UIColor clearColor];
[self addSubview:drawView];
NSDictionary *views = NSDictionaryOfVariableBindings(drawView);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[drawView]|"
options:0
metrics:nil
views:views];
[self addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[drawView]|"
options:0
metrics:nil
views:views];
[self addConstraints:constraints];
[drawView setDrawRectBlock:block];
if (completion != nil) {
completion(drawView);
}
}
}
@end
我认为问题出在代码的这一部分:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
if (_drawBlock) {
_drawBlock(context, rect);
_drawBlock = nil;
}
}
如果我评论这一行:
_drawBlock = nil;
似乎一切正常,但内存消耗不会停止而且应用变得非常慢。
有什么想法吗?子类不是一个选项。
谢谢!
更新1 使用示例
- (void)drawOnView {
[self.view drawInside:^(CGContextRef context, CGRect drawFrame) {
// Oblique lines
CGMutablePathRef obliquePath = CGPathCreateMutable();
CGFloat height = CGRectGetHeight(drawFrame);
for (CGFloat x = -height; x < CGRectGetWidth(drawFrame); x += 7.5) {
CGPathMoveToPoint(obliquePath, nil, x, 0.0);
CGPathAddLineToPoint(obliquePath, nil, x + height, height);
}
CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:0.0 alpha:0.04].CGColor);
CGContextSetLineWidth(context, 2.0);
CGContextAddPath(context, obliquePath);
CGContextStrokePath(context);
CGPathRelease(obliquePath);
} withResult:^(UIView *view) {
[self.view sendSubviewToBack:view];
}];
}
答案 0 :(得分:0)
首先,应该复制块,而不是保留块。在strong
属性声明中将copy
替换为drawBlock
。
接下来,你是对的,你不应该阻止阻止,因为DrawingView
drawRect:
需要重新显示。
内存问题可能是保留周期。确保你不会从街区内进入自己,也不会进入伊娃。
之后弱化自我之外的自我__weak typeof(self) weakSelf = self;
[self drawInside:^{
// use only weakSelf
} ...
如果这对您的块显示drawInside:
调用示例没有帮助。另外,你从哪里来称呼它?
最后,假设DrawingView
采用其完整的超视图大小,单个DrawingView
可以更有效地将绘制块存储在内部数组中,并从单个{{{ 1}}打电话。为每个块创建一个新的drawRect
,根本没有约束,似乎有点开销。
但这更为先进,我建议你先把基本案例搞定。