在ARC上对__bridge使用CoreGraphics渐变时,应用程序崩溃 [英] App crashes when using __bridge for CoreGraphics gradient on ARC

查看:79
本文介绍了在ARC上对__bridge使用CoreGraphics渐变时,应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为iOS 5创建一个应用程序,并且正在绘制一些渐变.我在ARC之前一直使用下面的渐变代码,但是当我多次使用它时,它现在不再在我的设备上运行(但是,它在模拟器上运行)(所以我认为这是内存管理问题).无论如何,这是代码:

I'm creating an application for iOS 5 and I'm drawing some gradients. The following gradient code I've always used before ARC, but now it does not work on my device anymore (however, it works on the simulator) when I use it several times (so I suppose it's a memory management issue). Anyways, here's the code:

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

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

CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);

CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));

CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);

CGGradientRelease(gradient);

最初,没有__bridge语句,我根据Xcode的建议添加了它们.到底是什么引起了问题?

Originally, there were no __bridge statements, I added them as suggested by Xcode. What exactly is causing the problem?

推荐答案

您的问题可能与startColor等变量的生命周期有关.我猜这些可能是通过UIColor的-CGColor方法在您列出的代码之上的某个时刻创建的CGColorRefs.

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.

正如我在此答案中所述,除非您明确保留这些CGColorRef,否则它们可能会在生成的UIColor之后消失他们已经被释放.考虑到从中提取CGColorRefs之后再也不会使用UIColors,因此ARC可能会决定在有机会使用CGColorRefs之前取消分配这些UIColors.我已经看到模拟器和实际设备之间的对象寿命有所不同,因此这可以解释一个崩溃的原因,而不能解释另一个崩溃的原因.

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.

我对此的解决方案是使用立即转换为id的方法,如下所示:

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];

在转移CGColorRefs所有权方面,编译器会做正确的事情.

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

还有可能将NSArray提前释放,在这种情况下,以下代码可以确保将其挂起足够长的时间:

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);

这将NSArray跨接至Core Foundation,留下了保留数至少为1的CFArrayRef.您可以在创建渐变时使用它,希望渐变可以保留对其的引用,然后手动释放它完成后.

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.

但是,Bringo建议完全在Core Graphics的C API中工作,这可能是最简单的方法.我只是以为我会解释您的问题的潜在根源,以防将来您遇到类似的情况.

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.

这篇关于在ARC上对__bridge使用CoreGraphics渐变时,应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆