2012-02-09 4 views
7

私は、私が概説しようとしている問題を解決する方法を知っていますが、なぜコードシナリオがiOSシミュレータで動作しますが、私のiPadでは動作しないのか、ちょっと困惑しています。既存のCGColorをCGColorプロパティに割り当てると、iOSデバイスではなくiOSシミュレータで機能します。どうして?

私はさまざまなプロパティをチェックし、プロパティの状態に応じて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. 

上記のコードはSimulatorで問題なく動作します。ただし、iPadでアプリケーションを実行すると、backgroundColor割り当て時にクラッシュします。

これは、CGColor変数を取り除き、私のswitch/caseステートメントの中から直接バックグラウンドカラーを割り当てることで解決できます。これが私がやっていることです。

しかし、私は好奇心が強いです。なぜこれはある環境で動作し、他の環境では動作しないのでしょうか?

UPDATE

カップルの事。まず、iOS 5デバイスをターゲットにした、Xcode 4.2を使用したARCプロジェクトです。また、私のカラー割り当てコードは、アプリケーション全体を通してすべて参照されているため、これらの色を設定するために使用する一連の定義があるため、まったく同じではありません。コンパイラ私の定義に私のレフリーへのREFを交換する必要がありますので、私は自分のコードを簡素化しようとした

#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 

これは#define文の数がどのように見えるかです。それでも、それだけで言及する価値があります。

+0

あなたは、各ビルドにQuartzCoreフレームワークが含まれていることを確認してくださいましたか? –

+1

私はあなたの 'CGColor'で構築することさえできません。おそらく' CGColorRef'を意味します。 –

+0

私はフレームワークを追加し、この割り当てを行っているコードファイル内のヘッダを参照しました。 – RLH

答えて

8

ここに私の勘違いがあります:CGColorを渡す前に、それを作成した(そして唯一の参照を保持している)UIColorが破壊されている可能性があります。 CGColorRefの参照カウントはARCの下で処理されないため、CGColorを使用する前に、それを保持しているUIColorが破棄された場合、その色はダングリングリファレンスになります。

ARCには、オートレリースされたオブジェクトが決して自動解放プールに追加されない可能性があり、代わりにobjcオブジェクトが参照されなくなった後にreleasedが最適化されます。これは3つの組み合わせです。

  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


同様の問題はここで見られた。そのためARCの

EXC_BAD_ACCES drawing shadow

+0

削除したばかりのメッセージは無視してください。マジック!これで問題は解決しました。 QuartzCoreがiOSからOSX上のメモリを管理する方法には大きな違いがありますか?これは私がマイナーな、メモリ管理の奇妙さを見たのは初めてではありませんが、これは確かに奇妙なことです。 – RLH

+0

@RLHクォーツではありません - それはARCとコンパイラとの関係です(これは私の勘違いですが、実際のプロジェクトでARCを使用していないので、@ 100%を確認するためにobjcランタイムの最新実装を読んでいません) 。ランタイムは、場合によってはスレッドローカルストレージを使用します。 MRCで自動リリースされるオブジェクトは、自動解放プールに追加されることはありません。代わりに、コンパイラは、いくつかのランタイムの下でリリースメッセージを出すものを追加します(当然、これはあなたがそれを使い終えた後に起こります)。実装に関するいくつかの詳細については、私の答えにリンクを追加しました。 – justin

+0

リンクのおかげで、私は答えとしてマークしました。なぜなら、ここにいる誰かがApple独自のコードを使ってこれらのフレームワークやコンパイラを動作させない限り、直接的な(認識可能な)答えは存在しないからです。あなたの記事はかなり深く見える - 今週末にそれをチェックする。 – RLH

0

私たちのインスタンスmyCGLayerは派生したものではありませんが、CGLayerにはbackgroundColorというプロパティがないため、CGLayerから派生したものではありません。だから私は(再び)推測している、渡されるパラメータはUIColor型でCGColorではないはずです。 CGColorはCFTypeクラスから派生したものです。 UIColorはNSObjectから派生しています。それらは交換可能であってはなりません。私の推測が正しければ、私はそれがシミュレータで動作するのに驚いています。

私の推測が間違っていると、私を強く叩かないでください。

+0

彼らはおそらくCALayerを意味しました。彼らは実際に説明でCALayerを言った。 – Chuck

+0

努力のおかげで、それは私の間違いでした。私はすべてのサンプルコードを入力したので、カットアンドペーストはしません。チャックは正しいです - これは 'CALayer'です。これを反映するためにサンプルの変数を更新しました。 – RLH

+0

これは、実際のコードにそのようなタイプミスがない場合には、違いがあります。 – Jim

4

色をメソッドの終わりに早すぎるリリースされます。

私が使用

CGColorRetain

CGColorRef whiteColor = CGColorRetain([UIColor colorWithRed:1.0 green:1.0 
             blue:1.0 alpha:1.0].CGColor); 
関連する問題