I know how to fix the problem that I am about to outline, however, I am a bit baffled as to why the code scenario works in the iOS simulator but not on my iPad.
I have a method that checks various properties, and then sets the background color of a CALayer
depending on the state of a property. The following code is similar to my method of color assignment:
//This will be the CALayer BGColor...
CGColor c = UIColor.blueColor.CGColor; //Blue is the default
switch (myState)
{
case state_one:
c = UIColor.greenColor.CGColor;
//... more code ...
break;
case state_two:
c = UIColor.redColor.CGColor;
//... more code ...
break;
case state_three: //multiple cases are like the state_three case.
//Other code, but I don't need to assign the color. Blue works...
}
myCALayer.backgroundColor = c; //Oh-noes!!! Here we get the dreaded EXC_BAD_ACCESS on iPad
//...more code dealing with the layer.
The code above works without trouble in the Simulator. However, when I run the application on my iPad, it crashes at the backgroundColor
assignment.
I can fix this by getting rid of the CGColor
variable and assigning the background color from directly within my switch/case statement, and that's what I'm planning on doing.
However, I am curious. Why would this work in one environment and not the other?
UPDATE
Couple things. First, it's worth mentioning that this is an ARC project, using Xcode 4.2, targeting iOS 5 devices. Also, my color assignement code isn't entirely what it looks like because I have a series of defines that I use to set these colors because they are referenced all throughout my application.
This is what a few of the #define
statements looks like:
#define BLUE [UIColor colorWithRed:8.0/255.0 green:80.0/255.0 blue:150.0/255.0 alpha:1.0].CGColor
#define GREEN (UIColor.blueColor.CGColor)
//...and there are about 6 other colors
I tried to simplify my code because the compiler should replace the refs to my refs to my defines. Still, it's worth mentioning just in case.
Here's my hunch: It's possible that the
UIColor
that created it (and held its only reference) has been destroyed before you pass theCGColor
. SinceCGColorRef
's reference counting is not handled for you under ARC, the color would be a dangling reference if theUIColor
that held it were destroyed before you use theCGColor
.ARC has an optimization where "autoreleased" objects may never be added to an autorelease pools, and instead,
released
after the objc object is no longer referenced. This is a combination of three things:Knowing that, I suspect this program would rectify the problem:
In more detail, there are number of ways the compiler and the objc runtime can interpret and execute your program. This means that this problem could affect you when you change compiler versions, or when the runtime (OS) is updated. It can also happen as the libraries you use are updated or built with different versions or compiler settings. For example: If the library switches to ARC along the way, it may use a different runtime calls, or the calls may utilize thread local data differently if the compiler injected calls are updated.
Details about the ARC spec as it relates to the runtime can be found here: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime
A similar problem was seen here:
EXC_BAD_ACCES drawing shadow
You don't say what your instance
myCGLayer
us derived from, but I'll take a shot and say it's not derived from CGLayer, because CGLayer doesn't have abackgroundColor
property. So I'm guessing (again), the parameter passed should be of type UIColor and not CGColor. CGColor is derived from class CFType. UIColor is derived from NSObject. They shouldn't be interchangeable. If my guesses are right, I'm surprised it works in the simulator.Don't slap me too hard if my guesses are wrong.
Because of ARC the color is released too early in the end of the method.
i use: CGColorRetain