EXC_BAD_ACCES drawing shadow

2019-04-11 18:36发布

I am trying to add a shadow to my UIView, but in my drawRect method I get an EXC_BAD_ACCESS. (I am using ARC)

-(void) drawRect:(CGRect)rect {

    CGColorRef lightColor =  [UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f blue:216.0f/255.0f alpha:0.8].CGColor;

    CGColorRef shadowColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.4].CGColor;   

    CGContextRef context = UIGraphicsGetCurrentContext();
    // Draw shadow
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, CGSizeMake(-5, 0), 10, shadowColor);
    CGContextSetFillColorWithColor(context, lightColor);
    CGContextFillRect(context, _coloredBoxRect);
    CGContextRestoreGState(context);
}

Error Message: Thread 1: Program received signal: "EXC_BAD_ACCESS".

Line: CGContextSetFillColorWithColor(context, lightColor);

When I change this line to:

[[UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f blue:216.0f/255.0f alpha:0.8] setFill];

I get the same error but on this line:

CGContextSetShadowWithColor(context, CGSizeMake(-5, 0), 10, shadowColor);

Update I finally resolved the issue by changing:

CGColorRef shadowColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.4].CGColor;

to

float components[4] = {0, 0, 0, 1.0/3.0}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGColorRef shadowColor = CGColorCreate( colorSpace, components);

The eventual (working) code:

-(void) drawRect:(CGRect)rect 
{
    float components[4] = {0, 0, 0, 1.0/3.0};
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGColorRef shadowColor = CGColorCreate( colorSpace, components);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Draw shadow
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, CGSizeMake(-5, 0), 10, shadowColor);
    CGContextSetFillColorWithColor(context, lightColor);

    [[UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f blue:216.0f/255.0f alpha:0.8] setFill];

    CGContextRestoreGState(context);
}

4条回答
Luminary・发光体
2楼-- · 2019-04-11 19:19

I can't see any reason why that would crash, but try setting your color using this code instead of using a CGColorRef. If it doesn't fix the crash at least you'll know that line wasn't the problem:

[[UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f blue:216.0f/255.0f alpha:0.8] setFill];
查看更多
甜甜的少女心
3楼-- · 2019-04-11 19:25

Alternately you can tell the compiler to add your UIColor objects to the autorelease pool and not immediately release them.

UIColor * __autoreleasing lightUIColor = [UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f blue:216.0f/255.0f alpha:0.8];
CGColorRef lightColor =  lightUIColor.CGColor;

UIColor * __autoreleasing shadowUIColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.4];
CGColorRef shadowColor = shadowUIColor.CGColor;   
查看更多
闹够了就滚
4楼-- · 2019-04-11 19:26

The below code will satisfy ARC:

UIColor *lightColor =  [UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f blue:216.0f/255.0f alpha:0.8];
...
CGContextSetFillColorWithColor(context, lightColor.CGColor);

The reason for a crash that ARC deallocated interim UIColor* object just right after you created it.

查看更多
虎瘦雄心在
5楼-- · 2019-04-11 19:29

The UIColor may not make it into an autorelease pool when ARC's enabled. If it is not put in a pool and immediately released, the CGColors you reference (lightColor, shadowColor) would also have been deallocated by the time you pass it because they are held/owned by the UIColor, and no measure has been taken to ensure that these (non-NSObject) references remain valid beyond that scope.

I can't reproduce your exact issue, but I can reproduce it using:

CGColorRef shadowColor =
  [[UIColor alloc] initWithRed:0.2 green:0.2 blue:0.2 alpha:0.4].CGColor;

when run on the sim v5.0.

Have you posted the exact example? What OS version are you running on? Does it happen in all OS versions? Perhaps you should have a peek at the asm.

查看更多
登录 后发表回答