App crashes when using __bridge for CoreGraphics gradient on ARC

丶灬走出姿态 提交于 2019-12-06 10:38:08
Brad Larson

Your issue might be with the lifetime of the startColor, etc. variables. I'm guessing that these might be CGColorRefs created via UIColor's -CGColor method at some point above the code you've listed.

As I describe in this answer, unless you explicitly retain those CGColorRefs, they may go away after the UIColor that generated them has been deallocated. Given that you never use the UIColors again after you've extracted the CGColorRefs from them, ARC may decide to deallocate these UIColors before you've had a chance to use the CGColorRefs. I've seen object lifetimes differ between the Simulator and actual devices, so this could explain the crash on one but not the other.

My solution to this has been to use an immediate cast to id, like in the following:

NSArray *colors = [NSArray arrayWithObjects:(id)[color1 CGColor],
                                            (id)[color2 CGColor], nil];

where the compiler does the right thing as far as transferring ownership of the CGColorRefs.

There's also the possibility that your NSArray is being deallocated early, in which case the following code might make sure it hangs around long enough:

NSArray *colors = [NSArray arrayWithObjects:(__bridge id)startColor, (__bridge id)endColor, nil];

CFArrayRef colorArray = (__bridge_retained CFArrayRef)colors;
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colorArray, locations);
CFRelease(colorArray);

This bridges the NSArray across to Core Foundation, leaving behind a CFArrayRef with a retain count of at least 1. You can then use that in your gradient creation, where the gradient will hopefully keep a reference to it, and release it manually when done.

However, Bringo's suggestion to work entirely within Core Graphics' C API for this might be the easiest way to go here. I just thought I'd explain a potential source of your problems, in case you run into something similar in the future.

I ran into this exact same issue. I have resorted to using CGGradientCreateWithColorComponents which solves the problem for me. You have to convert your NSArray of CGColorRefs to an array of CGFloats.

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[2] = { 0.0, 1.0 };

CGFloat components[8] = { 0.909, 0.909, 0.909, 1.0,  // Start color
                          0.698f, 0.698f, 0.698f, 1.0 }; // End color

CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components,
                                     locations, 2);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!