0

I have a custom view with a sublayer (CAShapeLayer) and subview (UILabel). When I create the layer in initWithCoder and set the background color, it always shows up as black. However, if I move the code into initWithFrame, the color shows up successfully.

Are we not supposed to create sublayers in initWithCoder?

Here is the only way I can get my code to work:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.colorLayer = [CAShapeLayer layer];
        self.colorLayer.opacity = 1.0;
        [self.layer addSublayer:self.colorLayer];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {

        self.textLabel = [[UILabel alloc] initWithFrame:self.bounds];
        self.textLabel.font = [UIFont primaryBoldFontWithSize:12];
        self.textLabel.textColor = [UIColor whiteColor];
        self.textLabel.textAlignment = NSTextAlignmentCenter;
        self.textLabel.backgroundColor = [UIColor clearColor];
        [self addSubview:self.textLabel];
    }

    return self;

}

- (void)drawRect:(CGRect)rect {
    //Custom drawing of sublayer
}

UPDATE:

Turns out in my drawRect I was setting the fill color wrong. I should have used colorLayer.fillColor = myColor.CGColor instead of [myColor setFill] then [path fill]

dmoss18
  • 867
  • 1
  • 12
  • 25

1 Answers1

1

The difference between initWithFrame: and initWithCoder: is that initWithCoder: is called when the view is created from storyboard/nib.

If you add it programatically, for example:

UIView *v = [[UIView alloc] initWithFrame:...];
[self.view addSubview:v];

initWithFrame: is called.

The good idea is to create base init method and call it in both init. In that way the initialisation sets up all of the properties in both scenario, when the view is added programatically or in storyboard.

For example:

-(void)baseInit {
    self.colorLayer = [CAShapeLayer layer];
    self.colorLayer.opacity = 1.0;
    //... other initialisation
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self baseInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {

        [self baseInit];
    }

    return self;
}
Greg
  • 25,317
  • 6
  • 53
  • 62
  • But when I create the sublayer AND the uilabel in the same place (initWithCoder, for example), the sublayer's background is ALWAYS black. I don't understand why that happens. Also, apparently initWithFrame is never called, but the sublayer is still initialized. That makes no sense if what you're saying is true. – dmoss18 Aug 18 '14 at 15:59
  • If you don't believe just add log to both of that init and you will see that just one will be called. Try add layer to the view and after that add layer of the label to the sublayer: [self.colorLayer addSublayer:self.textLabel.layer]; [self.layer addSublayer:self.colorLayer]; – Greg Aug 18 '14 at 16:07