CGContextStrokePath 在 iOS > 5 中触发 EXC_BAD_ACCESS [重复]
Posted
技术标签:
【中文标题】CGContextStrokePath 在 iOS > 5 中触发 EXC_BAD_ACCESS [重复]【英文标题】:CGContextStrokePath triggers EXC_BAD_ACCESS in iOS > 5 [duplicate] 【发布时间】:2012-06-27 15:08:52 【问题描述】:我有一个自定义 UIButton 类,它为 UIButton 添加渐变和光泽效果 该代码在 ios 4 和 iOS5 模拟器上完美运行,但是当我在 iOS 5 设备上运行它时,它给了我异常 EXC_BAD_ACCESS ,该异常由以下行触发:
CGContextStrokePath(context);
非常感谢任何帮助, 这是我的代码
- (void)drawRect:(CGRect)rect
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat actualBrightness = _brightness;
if (self.selected)
actualBrightness -= 0.10;
CGColorRef blackColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0].CGColor;
CGColorRef highlightStart = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.7].CGColor;
CGColorRef highlightStop = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
CGColorRef outerTop = [UIColor colorWithHue:_hue saturation:_saturation brightness:1.0*actualBrightness alpha:1.0].CGColor;
CGColorRef outerBottom = [UIColor colorWithHue:_hue saturation:_saturation brightness:0.80*actualBrightness alpha:1.0].CGColor;
CGFloat outerMargin = 7.5f;
CGRect outerRect = CGRectInset(self.bounds, outerMargin, outerMargin);
CGMutablePathRef outerPath = createRoundedRectForRect(outerRect, 6.0);
// Draw gradient for outer path
CGContextSaveGState(context);
CGContextAddPath(context, outerPath);
CGContextClip(context);
drawLinearGradient(context, outerRect, outerTop, outerBottom);
CGContextRestoreGState(context);
if (!self.selected)
CGRect highlightRect = CGRectInset(outerRect, 1.0f, 1.0f);
CGMutablePathRef highlightPath = createRoundedRectForRect(highlightRect, 6.0);
CGContextSaveGState(context);
CGContextAddPath(context, outerPath);
CGContextAddPath(context, highlightPath);
CGContextEOClip(context);
drawLinearGradient(context, CGRectMake(outerRect.origin.x, outerRect.origin.y, outerRect.size.width, outerRect.size.height/3), highlightStart, highlightStop);
CGContextRestoreGState(context);
drawCurvedGloss(context, outerRect, 180);
CFRelease(highlightPath);
else
//reverse non-curved gradient when pressed
CGContextSaveGState(context);
CGContextAddPath(context, outerPath);
CGContextClip(context);
drawLinearGloss(context, outerRect, TRUE);
CGContextRestoreGState(context);
if (!_toggled)
//bottom highlight
CGRect highlightRect2 = CGRectInset(self.bounds, 6.5f, 6.5f);
CGMutablePathRef highlightPath2 = createRoundedRectForRect(highlightRect2, 6.0);
CGContextSaveGState(context);
CGContextSetLineWidth(context, 0.5);
CGContextAddPath(context, highlightPath2);
CGContextAddPath(context, outerPath);
CGContextEOClip(context);
drawLinearGradient(context, CGRectMake(self.bounds.origin.x, self.bounds.size.height-self.bounds.size.height/3, self.bounds.size.width, self.bounds.size.height/3), highlightStop, highlightStart);
CGContextRestoreGState(context);
CFRelease(highlightPath2);
else
//toggle marker
CGRect toggleRect= CGRectInset(self.bounds, 5.0f, 5.0f);
CGMutablePathRef togglePath= createRoundedRectForRect(toggleRect, 8.0);
CGContextSaveGState(context);
CGContextSetLineWidth(context, 3.5);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextAddPath(context, togglePath);
CGContextStrokePath(context);
CGContextRestoreGState(context);
CFRelease(togglePath);
// Stroke outer path
CGContextSaveGState(context);
CGContextSetLineWidth(context, 0.5);
CGContextSetStrokeColorWithColor(context, blackColor);
CGContextAddPath(context, outerPath);
CGContextStrokePath(context);
CGContextRestoreGState(context);
CFRelease(outerPath);
我现在真正想要的是它真的与 iOS 5 相关还是我做错了什么?
【问题讨论】:
这是一个相对较长的调试方法,尤其是在无法访问您拥有的自定义函数的情况下。设置一些断点并尝试找出在此方法中它中断的位置。我猜你们中的一个 Ref 并不是你想象的那样。 那么异常是在 CGContextStrokePath(Context) 引发的,它是 SDK 的一部分,让我感到困惑的是,这段代码在 iOS 4 上完美运行,甚至在 iOS 5 模拟器上也无法正常工作在任何 iOS 5 设备上 该代码中还有分支(if-else-statements)。哪个CGContextStrokePath()
让你崩溃了?
@DavidRönnqvist 实际上执行哪个分支并不重要,当执行“CGContextStrokePath(context)”方法时,代码会崩溃
【参考方案1】:
发生崩溃是因为当您访问 CGColorRefs 时 UIColors 已被释放。
避免这种情况的简单方法是使用
UIColor* blackColor = [UIColor blackColor];
CGContextSetStrokeColorWithColor(context, [blackColor CGColor]);
而不是
CGColorRef* blackColor = [[UIColor blackColor] CGColor];
CGContextSetStrokeColorWithColor(context, blackColor);
所以 ARC 没有机会提前释放 UIColor 对象。
【讨论】:
我一直在研究一个非常棘手的崩溃数周,我认为这个答案可能已经解决了它。谢谢!以上是关于CGContextStrokePath 在 iOS > 5 中触发 EXC_BAD_ACCESS [重复]的主要内容,如果未能解决你的问题,请参考以下文章
UIScrollView 捏放大到 CGContextStrokePath 而不改变线宽
iOS - NSInternalInconsistencyException 在 iOS 9 和 10 上发生,但在 iOS 11 上运行良好