uiimageviewuiimagecalayerviewdidappear

Sublayer is not visible unless added after viewDidAppear


I am trying to load a profile image for an app, but I want to add a white border to it and make it circular before I display it. In order to do that I set the image property on the UIImageView and then prepare the image by setting the appropriate corner radius, masking it to the bounds and then adding a white border sublayer. Originally, I was loading the image in over the internet asynchronously and everything worked fine because the image appeared after the view had appeared. However, when I cached the image and tried to prepare it before the imageView was shown on screen I couldn't get the border sublayer to display. It still masked properly, just no border. The code that I am using to prepare the image is below.

- (void)prepareProfileImage
{
    CALayer *imageLayer = self.profileImageView.layer;
    imageLayer.borderColor = [UIColor whiteColor].CGColor;
    imageLayer.allowsEdgeAntialiasing = NO;
    [imageLayer setCornerRadius:PROFILE_IMAGE_DIAMETER/2.0];
    [imageLayer setMasksToBounds:YES];

    CALayer *borderLayer = [CALayer layer];
    CGRect borderFrame = CGRectMake(-1.0, -1.0, (self.profileImageView.frame.size.width+2.0), (self.profileImageView.frame.size.height+2.0));
    [borderLayer setBackgroundColor:[[UIColor whiteColor] CGColor]];
    [borderLayer setFrame:borderFrame];
    [borderLayer setCornerRadius:PROFILE_IMAGE_DIAMETER/2.0];
    [borderLayer setBorderWidth:PROFILE_IMAGE_BORDER_WIDTH+1.0];
    [borderLayer setBorderColor:[UIColor whiteColor].CGColor];

    [imageLayer addSublayer:borderLayer];
}

This method works fine as long as it's called after viewDidLoad, but will not add the border layer if called before viewDidLoad. I have confirmed that self.profileImageView has been allocated at the time of this method call, but I only get the circular image, no border.

Is there something that I am misunderstanding about CALayers? Should it matter when I add the layer as a sublayer?

The reason I am not using the border property directly on the image layer is that it leaves a tiny sliver of image around the outside that is displeasing.


Solution

  • I have found the answer! The problem was that I want setting the frame of the border layer using the profileImageView frame, but because I am using autolayout that property is not set until after the view is displayed on screen.

    I ended up doing:

     /*! This function adds a border layer to the profile image view. */
    - (void)addBorderLayerToProfileImageView {
        CALayer *borderLayer = [CALayer layer];
        CGRect borderFrame = CGRectMake(-1.0, -1.0, (PROFILE_IMAGE_DIAMETER+2.0), (PROFILE_IMAGE_DIAMETER+2.0));
        [borderLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
        [borderLayer setFrame:borderFrame];
        [borderLayer setCornerRadius:PROFILE_IMAGE_DIAMETER/2.0];
        [borderLayer setBorderWidth:PROFILE_IMAGE_BORDER_WIDTH+1.0];
        [borderLayer setBorderColor:[UIColor whiteColor].CGColor];
        [self.profileImageView.layer addSublayer:borderLayer];
    }
    

    The reason I was adding a border layer at all is because the border on the layer leaves a small artifact between the edge of the image view and the border.