Пользовательский UIView drawRect никогда не вызывается, если начальный кадр CGRectZero

У меня есть довольно простой пользовательский подкласс 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 для этого класса с некоторым ненулевым прямоangularьником, он работает нормально; но когда я вызываю initWithFrame: CGRectZero, drawRect вызывается никогда, даже после того, как я изменяю рамку вида на ненулевой прямоangularьник.

Я, конечно, понимаю, почему представление с нулевым фреймом никогда не будет вызывать drawRect: call, но почему оно никогда не вызывается даже после изменения фрейма?

Ответ 1

Быстрый взгляд на документы Apple говорит об этом

Изменение прямоangularьника рамки автоматически переотображает представление, не вызывая его drawRect: метод. Если вы хотите, чтобы UIKit вызывал метод drawRect: при изменении прямоangularьника рамки, установите для свойства 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