简体   繁体   English

CAShapeLayer上的CAGradientLayer SetMask崩溃了

[英]CAGradientLayer SetMask on CAShapeLayer crashes app

Using example code from many great people , I am able to make a complex shape using CAShapeLayer and present that no problem using a subclassed UIView: 使用示例代码许多 伟大的 ,我能够让使用CAShapeLayer和现在,使用一个子类的UIView没有问题的复杂形状:

@implementation BMTestLogo

+ (Class)layerClass {
    return [CAShapeLayer class];
}


- (void)layoutSubviews {
    [self setUpPaths];
    [self setLayerProperties];
    //    [self attachAnimations];
}

- (void)setLayerProperties {
    CAShapeLayer *layer = (CAShapeLayer *)self.layer;
    //    _gradient = [CAGradientLayer layer];

    CGMutablePathRef combinedPath = CGPathCreateMutableCopy([[_UIBezierPathsArray objectAtIndex:0] CGPath]);

    for (UIBezierPath* path in _UIBezierPathsArray) {
        CGPathAddPath(combinedPath, NULL, path.CGPath);
    }

    layer.path = combinedPath;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.fillRule = kCAFillRuleEvenOdd;
}

This code works great, now trying to add a CAGradientLayer and mask over the shape, I keep getting a crash, specifically: QuartzCore CA::Layer::ensure_transaction_recursively(CA::Transaction*): 这段代码很好用,现在尝试在形状上添加CAGradientLayer和蒙版,但我一直崩溃,尤其是: QuartzCore CA::Layer::ensure_transaction_recursively(CA::Transaction*):

Here is the Gradient Code, note, this is taken from other, working examples on SO: 请注意,这是渐变代码,该代码取自SO上其他有效的示例:

@implementation BMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [_testLogo setNeedsDisplay];

    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.startPoint = CGPointMake(0.5,1.0);
    gradientLayer.endPoint = CGPointMake(0.5,0.0);
    gradientLayer.frame = CGRectMake(CGRectGetMinX(_testLogo.layer.bounds), CGRectGetMinY(_testLogo.layer.bounds), CGRectGetWidth(_testLogo.layer.bounds), CGRectGetHeight(_testLogo.layer.bounds));
    NSMutableArray *colors = [NSMutableArray array];
    for (int i = 0; i < 2; i++) {
        [colors addObject:(__bridge id)[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1].CGColor];
    }
    gradientLayer.colors = colors;
    NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
    NSNumber *stopTwo  = [NSNumber numberWithFloat:1.0];
    NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, nil];
    gradientLayer.locations = locations;
    gradientLayer.needsDisplayOnBoundsChange = YES;
    [gradientLayer setMask:_testLogo.layer];
    [_testLogo.layer insertSublayer:gradientLayer atIndex:0];

    // Do any additional setup after loading the view, typically from a nib.
}

I have tried to debug and research this issue, and the usual suspects of the UIColors not being CGColors or (__bridge id) properly are not there, I am using two locations for the gradient, with only 2 colors, and moreover I have tried dozens of different versions: with or without setNeeds display, properties vs. local declarations, the gradient layer inside the sub class and out, all still giving me the same crash when inserting thesublayer. 我已经尝试调试和研究此问题,并且通常不存在UIColors可能不是CGColors或(__bridge id)的怀疑,我使用了两个位置进行渐变,仅使用了2种颜色,而且我尝试了数十种的不同版本:无论是否显示setNeeds,属性与局部声明,子类内部和外部的渐变层,在插入子层时都仍然给我同样的崩溃。

When I take out the setMask: call, it does not crash, and just fills the whole frame with the gradient. 当我取出setMask:调用时,它不会崩溃,而只是用渐变填充整个帧。

This seems like I'm just missing something minor or obvious. 似乎我只是缺少一些次要的或明显的东西。 Note, using iOS 6 and ARC -- would like to keep using CAShapeLayer and CAGradientLayer as it makes it a bit easier to animate (which is the end goal). 请注意,使用iOS 6和ARC-希望继续使用CAShapeLayer和CAGradientLayer,因为它可以使动画制作起来更容易(这是最终目标)。

The following code is triggering a stack overflow in ensure_transaction_recursively . 以下代码在ensure_transaction_recursively触发堆栈溢出。

[gradientLayer setMask:_testLogo.layer];
[_testLogo.layer insertSublayer:gradientLayer atIndex:0];

The shape layer has a gradient layer subview which has a shape layer mask which has a gradient layer subview... 形状层具有渐变层子视图,该子视图具有形状层蒙版,该形状层遮罩具有渐变层子视图...

Since your goal is to have a gradient layer that is masked by a shape, BMTestLogo should be backed by the CAGradientLayer which then has a the CAShapeLayer as its mask. 由于您的目标是要有一个被形状遮罩的渐变层,因此BMTestLogo应该由CAGradientLayer支持,然后将CAShapeLayer作为其遮罩。 The shape layer should never reference the gradient layer. 形状层永远不要引用渐变层。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM