如果初始帧为 CGRectZero,则不会调用自定义 UIView 的 drawRect

Posted

技术标签:

【中文标题】如果初始帧为 CGRectZero,则不会调用自定义 UIView 的 drawRect【英文标题】:Custom UIView's drawRect never called if initial frame is CGRectZero 【发布时间】:2011-05-27 18:56:00 【问题描述】:

我有一个非常简单的 UIView 自定义子类:

#import "BarView.h"
#import <QuartzCore/QuartzCore.h>

@implementation BarView

@synthesize barColor;

- (void)drawRect:(CGRect)rect

    NSLog(@"drawRect");
    // Draw a rectangle.
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, self.barColor.CGColor);
    CGContextBeginPath(context);
    CGContextAddRect(context, self.bounds);
    CGContextFillPath(context);


- (void)dealloc

    self.barColor = nil;

    [super dealloc];


@end

如果我用一些非零矩形在这个类上调用 initWithFrame:rect,它工作正常;但是当我调用 initWithFrame:CGRectZero 时,drawRect 永远不会被调用,即使在我将视图的框架修改为非零矩形之后也是如此。

我当然明白为什么一个零帧的视图永远不会调用它的 drawRect:,但为什么即使在帧改变后它也不会调用呢?

【问题讨论】:

【参考方案1】:

快速浏览一下 Apple 文档就说明了这一点

更改框架矩形会自动重新显示视图,而无需调用其 drawRect: 方法。如果希望 UIKit 在框架矩形发生变化时调用 drawRect: 方法,请将 contentMode 属性设置为 UIViewContentModeRedraw。

这在框架属性的文档中:https://developer.apple.com/documentation/uikit/uiview/1622621-frame?language=objc

如果您想重绘视图,只需调用 setNeedsDisplay 就可以了(或者,正如文档所说,您可以将其设置为 UIViewContentModeRedraw,但这取决于您)

【讨论】:

【参考方案2】:

在 Swift 5 中

override init(frame: CGRect) 
      super.init(frame: frame)

      contentMode = UIView.ContentMode.redraw

【讨论】:

真的,你应该只需要contentMode = .redraw

以上是关于如果初始帧为 CGRectZero,则不会调用自定义 UIView 的 drawRect的主要内容,如果未能解决你的问题,请参考以下文章

Redis自定义动态字符串(sds)模块

拷贝构造函数调用的三种情况

如果快速滑动,则不会调用 UIPageViewController didFinishAnimating

如果授权标头不存在,则无法在 Webfilter 中发送自定义正文

如果谓词使用 IN,则不会调用 NSFetchedResultsControllerDelegate 方法?

如果 ExceptionHandler 捕获到异常,则不会调用 DelegatingHandler