将现有 CGColor 分配给 CGColor 属性适用于 iOS 模拟器,而非 iOS 设备。为什么?

发布于 2025-01-03 23:16:41 字数 1419 浏览 2 评论 0原文

我知道如何解决我即将概述的问题,但是,我有点困惑为什么代码场景在 iOS 模拟器中有效,但在我的 iPad 上却无效。

我有一个方法可以检查各种属性,然后根据属性的状态设置 CALayer 的背景颜色。以下代码与我的颜色分配方法类似:

//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.

上面的代码在模拟器中运行没有问题。但是,当我在 iPad 上运行该应用程序时,它在 backgroundColor 分配时崩溃。

我可以通过删除 CGColor 变量并直接在 switch/case 语句中分配背景颜色来解决此问题,这就是我打算做的。

不过,我很好奇。为什么这在一种环境中有效,而在另一种环境中无效?

更新

一些事情。首先,值得一提的是,这是一个 ARC 项目,使用 Xcode 4.2,针对 iOS 5 设备。另外,我的颜色分配代码并不完全像它看起来的那样,因为我有一系列用于设置这些颜色的定义,因为它们在我的整个应用程序中被引用。

这就是一些 #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 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瑕疵 2025-01-10 23:16:41

由于 ARC,颜色在方法结束时过早释放。

我使用:CGColorRetain

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

Because of ARC the color is released too early in 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);
红衣飘飘貌似仙 2025-01-10 23:16:41

我的预感是:在传递 CGColor 之前,创建它(并保存其唯一引用)的 UIColor 可能已被销毁。由于在 ARC 下,CGColorRef 的引用计数不会为您处理,因此,如果在使用 之前保存颜色的 UIColor 被销毁,则该颜色将是悬空引用。 CG颜色

ARC 有一项优化,其中“自动释放”对象可能永远不会添加到自动释放池中,而是在 objc 对象不再被引用后释放。这是三件事的组合:

  1. 编译器版本和您使用的选项。毫不奇怪,编译器添加了引用计数,并且有一些变化。
  2. ObjC 运行时。运行时可以利用线程本地数据。当然,这可以包括您的堆栈。如果您详细了解对象如何绕过自动释放池,这应该会更清楚。
  3. 您使用的库(包括系统库和框架)。随着编译器和运行时的更新,库可能会使用 ARC,或者它们可能会使用不同的运行时调用来执行程序。

知道了这一点,我怀疑这个程序会纠正这个问题:

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.

更详细地说,编译器和 objc 运行时可以通过多种方式解释和执行您的程序。这意味着当您更改编译器版本或更新运行时 (OS) 时,此问题可能会影响您。当您使用的库更新或使用不同版本或编译器设置构建时,也可能会发生这种情况。例如:如果库一路切换到 ARC,它可能会使用不同的运行时调用,或者如果更新了编译器注入的调用,这些调用可能会以不同的方式利用线程本地数据。

有关 ARC 规范与运行时相关的详细信息可以在此处找到:
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime


这里也出现过类似的问题:

EXC_BAD_ACCES绘制阴影

Here's my hunch: It's possible that the UIColor that created it (and held its only reference) has been destroyed before you pass the CGColor. Since CGColorRef's reference counting is not handled for you under ARC, the color would be a dangling reference if the UIColor that held it were destroyed before you use the CGColor.

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:

  1. The compiler version and options you use. No surprise, the compiler adds the reference counting, and there are variations for this.
  2. The ObjC Runtime. The runtime may utilize thread local data. Naturally, this can include your stack. If you read into the details of how an object may bypass an autorelease pool, this should be clearer.
  3. The libraries you use (including system libraries and frameworks). As the compiler and runtimes are updated, the libraries may use ARC, or they may use different runtime calls to execute the program.

Knowing that, I suspect this program would rectify 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 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

荒路情人 2025-01-10 23:16:41

你没有说你的实例myCGLayer是从什么派生的,但我会说它不是从CGLayer派生的,因为CGLayer没有backgroundColor财产。所以我(再次)猜测,传递的参数应该是 UIColor 类型而不是 CGColor 类型。 CGColor 派生自 CFType 类。 UIColor 派生自 NSObject。它们不应该互换。如果我的猜测是正确的,我很惊讶它能在模拟器中工作。

如果我的猜测是错误的,请不要太用力地打我。

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 a backgroundColor 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文