Try the following amendment to Noah's code below. In effect the enumeration checks if there are defined mask layers as opposed to using the default layer.mask CALayer. I came across an interesting issue with UIImageViews trying to set this value.
CALayer *_layerImage = _imageViewBackground.layer;
CGRect _rect = _imageViewBackground.bounds;
__block CAGradientLayer *_maskLayer = nil;
[_layerImage.sublayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[CAGradientLayer class]]) {
_maskLayer = (CAGradientLayer*) obj;
*stop = YES;
}
}];
BOOL _found = YES;
if (!_maskLayer) {
_maskLayer = [CAGradientLayer layer];
_found = NO;
}
_maskLayer.colors = @[ (id)([UIColor redColor].CGColor), (id)([UIColor clearColor].CGColor) ]; // gradient from 100% opacity to 0% opacity (non-alpha components of the color are ignored)
// startPoint and endPoint (used to position/size the gradient) are in a coordinate space from the top left to bottom right of the layer: (0,0)–(1,1)
_maskLayer.startPoint = CGPointMake(0, 0);
_maskLayer.endPoint = CGPointMake(1, 1);
_maskLayer.frame = _rect; // line it up with the layer it’s masking
dispatch_async(dispatch_get_main_queue(), ^{
if (!_found) {
[_layerImage addSublayer:_maskLayer];
}
});
Hope that helps!