Assigning an existing CGColor object to the CGColor property works in iOS Simulator, not on an iOS device. What for?

I know how to fix the problem that I am going to describe, however I am a little puzzled by why the code script 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 CALayer depending on the state of the property. The following code is similar to my color assignment method:

 //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 above code works without problems in the simulator. However, when I launch the application on my iPad, it crashes with the purpose of backgroundColor .

I can fix this by getting rid of the CGColor variable and assigning the background color directly in my switch / case statement, and about what I plan to do.

However, I am curious. Why does this work in one environment and not in another?

UPDATE

A couple of things. First, it's worth mentioning that this is an ARC project using Xcode 4.2 targeting iOS devices 5. Also, my color assignment code is not exactly what it looks like, because I have a number of definitions that I use for setting these colors because they are listed throughout my application.

Here are some of the #define :

 #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 refs with my references to my definitions. However, it is worth mentioning just in case.

+7
source share
3 answers

Here is my hunch: it is possible that UIColor , which created it (and retained its only link), was destroyed before passing CGColor . Since the CGColorRef reference count is not processed for you in ARC, the color will be a sagging link if the UIColor that held it was destroyed before using CGColor .

ARC has an optimization where objects with auto-implementation can never be added to autocompletion pools, and instead released after the objc object is no longer referenced. This is a combination of three things:

  • The version and compiler options that you use. Not surprisingly, the compiler adds a reference counter, and there are options for this.
  • ObjC runtime. The runtime environment can use local stream data. Naturally, this may include your stack. If you read the details of how an object can bypass the autoplay pool, this should be clearer.
  • The libraries you use (including system libraries and frameworks). As the compiler and runtime updates, libraries may use ARC or may use different calls at runtime to execute the program.

Knowing that, I suspect that this program will fix the problem:

 UIColor * c = UIColor.blueColor; //Blue is the default switch (myState) { case state_one: c = UIColor.greenColor; //... more code ... break; case state_two: c = UIColor.redColor; //... 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... } myCGLayer.backgroundColor = c.CGColor; //...more code dealing with the layer. 

In more detail, there are many ways that the compiler and the objc runtime can interpret and execute your program. This means that this problem may affect you when changing compiler versions or when updating the runtime. This can also happen because the libraries that you use are updated or created with different versions or compiler settings. For example: if the library switches to ARC along the way, it may use different calls at runtime, or calls may use local stream data differently if updated calls with the compiler are updated.

Runtime ARC specifications can be found here: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime


A similar problem was seen here:

Shadow drawing EXC_BAD_ACCES

+8
source

Due to ARC, the color is displayed too early at the end of the method.

i use: CGColorRetain

 CGColorRef whiteColor = CGColorRetain([UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor); 
+4
source

You do not say what your myCGLayer instance myCGLayer , but I will take a picture and say that it is not obtained from CGLayer, because CGLayer does not have the backgroundColor property. Therefore, I assume (again), the parameter passed must be of type UIColor, not CGColor. CGColor is derived from the CFType class. UIColor is derived from NSObject. They should not be used interchangeably. If my guesses are correct, I am surprised that it works in a simulator.

Don't hit me too hard if my guesses are wrong.

0
source

All Articles