CGContextDrawLinearGradient导致EXC_BAD_ACCESS

时间:2015-03-29 18:09:11

标签: objective-c swift core-graphics linear-gradients bemsimplelinegraph

我正在配置我的BEMSimpleLineGraph并且除了线性渐变着色之外已经能够成功完成。在提供的示例Obj-C项目

中引用此代码之后
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat components[8] = {
        1.0, 1.0, 1.0, 1.0,
        1.0, 1.0, 1.0, 0.0
    };
    self.myGraph.gradientBottom = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);

并在Swift中将其转录为此内容:

let colorspace:CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()
        let num_locations:size_t = 2
        var locations: [CGFloat] = [0.0, 1.0]
        var components: [CGFloat] = [
            1.0, 1.0, 1.0, 1.0,
            1.0, 1.0, 1.0, 0.0
        ]

       self.myGraph.gradientBottom = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations)

所有内容都正确构建,但会在包含的BEMLine.m文件中抛出EXC_BAD_ACCESS内存错误,在此行停止

CGContextDrawLinearGradient(ctx, self.bottomGradient, CGPointZero, CGPointMake(0, CGRectGetMaxY(fillBottom.bounds)), 0);

我已经包含了obj-c桥接头,添加了CoreGraphics框架,在Storyboard中相应ViewController的属性窗格中启用了底色,引用了Apple的开发页面以确保所有参数的正确数据类型,但我仍然会来干了。在检查错误相似性时,我也意识到尝试绘制顶部线性渐变也会出现同样的错误。错误似乎在于试图绘制渐变的Obj-C代码,但我再次无法做什么。

3 个答案:

答案 0 :(得分:6)

使用Swift的BEMSimpleLineGraph时遇到了同样的问题。幸运的是,我在库Github的问题页面找到了答案:

https://github.com/Boris-Em/BEMSimpleLineGraph/issues/105

为了解决这个问题,我刚刚在Swift类中声明了一个全局渐变,如下所示:

var gradient  : CGGradient?

刚刚更换了

self.myGraph.gradientBottom = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations)

使用:

self.gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations)
self.myGraph.gradientBottom = self.gradient

显然,渐变将不会在内存中保留分配,并且在库需要使用时,它将不再可用。

答案 1 :(得分:0)

我注意到的一件事是,在设置代码中,您使用self.myGraph.gradientBottom而在绘图代码中使用self.bottomGradient

这些应该是一样的吗?或者你忘了为后者分配一个值?

答案 2 :(得分:0)

造成这种情况的根本原因是Swift和Objective-C对Foundation引用的内存管理方式有所不同。

在Objective-C中,ARC不会为您管理Foundation对象的保留计数。必要时调用CFRetain / CFRelease是开发人员的工作。

在Swift中,保留计数由您管理。实际上,您根本无法调用CFRetain / CFRelease!

在Swift中创建渐变并将其直接分配给Objective-C属性时,不会进行内存管理。由于没有强引用,因此已发布(不必立即发布)。

在objective-c中它不会为零,因此将进行检查,但是将释放渐变并且内存不再有效。

可接受的解决方案之所以有效,是因为有很强的参考-var梯度