22

In theory you can easily set the background color via:

self.backgroundColor = [UIColor redColor];

in drawRect, but this does does not have any effect. You can change the view's size, its borders, its subviews, etc., but not background Color. Similar SO queries suggest to add a subView or to change the backgroundColor in the initWithFrame or initWithCoder initialization messages. My question is why does it not work in drawRect when other characteristics can be changed?

Changing the view's layer backgroundColor also does nothing, perhaps for the same reason. What is the relationship between the view's backgroundColor and its layer's backgroundColor, since they are not the same?

farhadf
  • 1,918
  • 3
  • 19
  • 27

4 Answers4

26

If you set backgroundColor when the view is first configured (i.e., before the OS calls drawRect), that backgroundColor will be used without any further code on your part. As the UIView Class Reference says, the backgroundColor property is used to "set the view’s color rather than drawing that color yourself."

But if you attempt to set it in drawRect, the background fill has already been performed, so you won't immediately see the effect of changing the background color (unless you manually perform another fill yourself in drawRect). The drawRect method should be used for rendering the view, not for configuring it.

If the UIView sets the backgroundColor as the view is being configured (e.g. in whichever init method you avail yourself of), that background color will used, without any need to do anything else in drawRect.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks. Are there other view attributes that are preset by the time drawRect is called? I'm not exactly sure where configuration stops and rendering begins. I can, for example, set the view's frame or paint its borders, or if there is any text, set the text color. Are all these better set in the init methods? – farhadf May 27 '14 at 00:34
  • 1
    You should not be setting any properties of the view, of its `layer`, of any subviews or sublayers in `drawRect`. So, obviously, setting `frame` definitely should not be done in `drawRect`. Re borders, if you're doing that using the properties of the `layer`, that doesn't belong in `drawRect`, but if you're manually stroking/drawing a border, that could be done in `drawRect`. Re text color, if you're using a label/text field subview, configuring/setting that doesn't belong in `drawRect`, but if you're manually stroking/drawing the text, then you would do that in `drawRect`. – Rob Jul 14 '17 at 01:08
8

As Rob stated in his answer, the background has already been drawn when the drawRect method is called. If you need to change the background color at this point, you will have to draw it yourself:

[self.backgroundColor setFill];
CGContextFillRect(UIGraphicsGetCurrentContext(), rect);

So you still can change the value of the property, but it will not be used until the view is drawn again.

robert
  • 2,822
  • 1
  • 16
  • 19
4

Update for swift3 on drawRect function :

    self.backgroundColor = UIColor.red
    self.backgroundColor?.setFill()
    UIGraphicsGetCurrentContext()!.fill(rect);
Fares Benhamouda
  • 589
  • 8
  • 21
2

Set your background color into your awakeFromNib function:

// Objective-C
- (void)awakeFromNib {
    self.backgroundColor = [UIColor redColor];
}

// Swift
override func awakeFromNib() {
    backgroundColor = UIColor.red
}
Simon Germain
  • 6,834
  • 1
  • 27
  • 42