【问题标题】:UIView disappears after close and reopen the app [custom UIView category]关闭并重新打开应用后 UIView 消失 [自定义 UIView 类别]
【发布时间】:2014-07-17 01:04:19
【问题描述】:

我创建了一个 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];

    }];

}

【问题讨论】:

  • 在这种情况下,DrawBlock到底是什么?
  • 需要 _drawBlock 吗?我没有看到它在任何地方被调用。只有在设置 _drawBlock 时才会调用 setNeedsDisplay。
  • 你从哪里给drawOnView打电话?
  • drawInside 是块,不直接调用
  • 起来!抱歉,从 viewDidLoad 或 viewWillAppear 调用“drawOnView”。我尝试了多种方法,但没有任何效果

标签: ios objective-c uiview drawrect


【解决方案1】:

首先,块应该被复制,而不是保留。在drawBlock 属性声明中将strong 替换为copy

接下来,你是对的,你不应该将块归零,因为 DrawingView drawRect: 需要它重新显示。

内存问题可能是保留循环。确保您不要从块内访问 self 或其 ivars。在块外弱化自己为

__weak typeof(self) weakSelf = self;


[self drawInside:^{
    // use only weakSelf 
} ...

如果这无助于在您的块中显示 drawInside: 调用示例。还有,你是从哪里称呼它的?


最后,鉴于DrawingView 采用其完整的超级视图大小,使用单个DrawingView 将绘制块存储在内部数组中并从单个drawRect 调用中绘制所有这些块可能会更有效。为每个块创建一个新的DrawingView,完全有约束,似乎有点开销。

但这更高级,我建议你先把基本的情况下工作。

【讨论】:

  • 我试过 __weak 但不起作用。此外,一切都是在街区内完成的。谢谢
  • 谁能帮帮我?谢谢!
  • _drawBlock = nil 肯定是错误的,DrawingView 在需要重新显示时需要该块。如果没有这条线,您应该尝试找出导致性能变慢和内存泄漏的问题。
  • 是的,如果我这样做,“_drawBlock = nil”行会从 UIView 中消失,但会保留对此 UIView 的引用并造成泄漏。我还在调查中……
猜你喜欢
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多