CGContextDrawLinearGradient 导致 EXC_BAD_ACCESS
CGContextDrawLinearGradient causing EXC_BAD_ACCESS
我正在配置我的 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 桥接 header,添加了 CoreGraphics 框架,在 Storyboard 中相应 ViewController 的属性窗格中启用了底部颜色,参考了 Apple 的开发页面以确保所有参数的数据类型都是正确的,但我仍然很干。在检查错误相似性时,我还意识到在尝试绘制顶部线性渐变时也会出现同样的错误。错误似乎出在试图绘制渐变的 Obj-C 代码中,但我又一次不知所措。
我注意到的一件事是,在设置代码中使用 self.myGraph.gradientBottom
,而在绘图代码中使用 self.bottomGradient
。
这些应该是一样的吗?还是你忘记给后者赋值了?
我在使用 Swift 的 BEMSimpleLineGraph 时遇到了同样的问题。幸运的是,我在图书馆 Github:
的问题页面上找到了答案
https://github.com/Boris-Em/BEMSimpleLineGraph/issues/105
为了解决这个问题,我刚刚在Swiftclass中声明了一个全局梯度,像这样:
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
显然,否则梯度将不会保留在内存中,并且在库需要使用它时,它不再可用。
其根本原因是 Swift 和 Objective-C 以不同方式处理 Foundation 引用的内存管理。
在Objective-C中,ARC 不会为您管理 Foundation 对象的保留计数。必要时调用 CFRetain/CFRelease 是开发人员的工作。
在 Swift 中,保留计数是为您管理的。事实上你根本不能调用 CFRetain/CFRelease!
当您在 Swift 中创建渐变并将其直接分配给 objective-c 属性 时,不会进行内存管理。由于没有对它的强引用,它已发布(不需要立即发布)。
在objective-c中不会为nil,所以检查会通过,但是梯度会被释放,内存不再有效。
接受的解决方案有效,因为有一个强大的参考 - var gradient
我正在配置我的 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 桥接 header,添加了 CoreGraphics 框架,在 Storyboard 中相应 ViewController 的属性窗格中启用了底部颜色,参考了 Apple 的开发页面以确保所有参数的数据类型都是正确的,但我仍然很干。在检查错误相似性时,我还意识到在尝试绘制顶部线性渐变时也会出现同样的错误。错误似乎出在试图绘制渐变的 Obj-C 代码中,但我又一次不知所措。
我注意到的一件事是,在设置代码中使用 self.myGraph.gradientBottom
,而在绘图代码中使用 self.bottomGradient
。
这些应该是一样的吗?还是你忘记给后者赋值了?
我在使用 Swift 的 BEMSimpleLineGraph 时遇到了同样的问题。幸运的是,我在图书馆 Github:
的问题页面上找到了答案https://github.com/Boris-Em/BEMSimpleLineGraph/issues/105
为了解决这个问题,我刚刚在Swiftclass中声明了一个全局梯度,像这样:
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
显然,否则梯度将不会保留在内存中,并且在库需要使用它时,它不再可用。
其根本原因是 Swift 和 Objective-C 以不同方式处理 Foundation 引用的内存管理。
在Objective-C中,ARC 不会为您管理 Foundation 对象的保留计数。必要时调用 CFRetain/CFRelease 是开发人员的工作。
在 Swift 中,保留计数是为您管理的。事实上你根本不能调用 CFRetain/CFRelease!
当您在 Swift 中创建渐变并将其直接分配给 objective-c 属性 时,不会进行内存管理。由于没有对它的强引用,它已发布(不需要立即发布)。
在objective-c中不会为nil,所以检查会通过,但是梯度会被释放,内存不再有效。
接受的解决方案有效,因为有一个强大的参考 - var gradient