There’s a gotcha/bug if you’re using -[UIColor CGColor] to get a CGColorRef for use with CoreGraphics. I think several people have already documented this on their blogs, but I was having the same issue in my DTCalendarView when running it on device. The same code worked before enabling ARC, but with ARC enabled it there is a difference whether its running on device or simulator.
On Simulator all is fine. On device however you get a EXC_BAD_ACCESS because the ARC release the UIColor way before the end of the current scope. There are several possible workarounds but it is still unintuitive that previously working code ceases working with ARC.
We were told to also file bug reports for unexpected behaviors or something that is counter intuitive, so here you go… Radar #11717864 and OpenRadar. Here’s the sample project.
Update: Yes, I know that you could call this “works as designed”. But the point here is that it is non-obvious and causes previously working code to break. Even the gurus at the Big Nerd Ranch stumbled over this one and filed is filed. In the least I would expect an LLVM compiler warning for this to be added.
ARC releases UIColor prematurely
Summary
When assigning a UIColor’s CGColor to a CGColorRef for later use then ARC discards the UIColor too early when running on device.
Steps to Reproduce
Run the attached sample project.
Expected Results
App should run equally well on Simulator and Device. ARC should not release the UIColor before the end of the scope.
Actual Results
App runs ok on Simulator, but crashes on Device with EXC_BAD_ACCESS.
Regression
This was working fine before using it in a project without ARC since the code in question does not use NSObjects for anything except to create the two CGColorRefs.
Notes
A workaround is to save the UIColor in an IVAR to establish a strong reference. When doing this the exception no longer occurs. Another workaround apparently is to immediately CGColorRetain the CGColor.
Categories: Bug Reports
This does not seem to be a bug, it is a gotcha though. ARC does not deal with CGColorRef objects. Using CGColorRetain() or doing something like this would be the correct way of doing this:
UIColor *color = [UIColor …];
CGColorRef colorRef = color.CGColor;
Doing
CGColorRef colorRef = [UIColor …].CGColor;
was never the correct way of doing things.