2011-11-10 16 views
6

にCFArrayRefをキャストするとき、これは素晴らしいです:クラッシュNSArrayの

​​

これはEXC_BAD_ACCESSが発生します。NSArraydocumentationから

CFArrayRef windowIDList = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 
NSLog(@"Array %@", (__bridge NSArray*) windowIDList); 

答えて

8

NSArrayとして作成された配列には、Objective-Cオブジェクトのように動作する要素しか含めることができません。

CFArrayとして作成された配列には、適切なCFArrayCallBacksCFArrayCreateに渡すと何も含めることができます。

CGWindowListCreateCFArrayを作成し、オブジェクトのように動作しませんが、CGWindowListCreateはそれを気にしないCFArrayCallbacksを使用しているもので、それを埋めています。

あなたは%@書式指定子で、このCFArrayを印刷しようとすると、NSLogアレイにObjective-Cの-descriptionメッセージを送信します。 CFArrayはObjective-C descriptionメッセージを各要素に送信することでこれを処理します。残念ながら、その要素はオブジェクトではないため、Objective-Cメッセージを送信することは不可能です。したがって、クラッシュ。

代わりにこれを試してください。

CFStringRef description = CFCopyDescription(windowIDList); 
NSLog(@"Array %@", description); 
CFRelease(description); 

CFCopyDescription関数ではなくそれぞれにObjective-Cのメッセージを送信しようとする、配列の各要素にCFArrayCallbacks機能の1つを使用します。コールバックは配列要素をどのように扱うかを知っているので、うまく動作します。私は私のテストプログラムでは、この出力を得る:

2011-11-10 18:50:23.888 test[15156:707] <CFArray 0x1001140c0 [0x7fff7fd24ea0]>{type = mutable-small, count = 19, values = (
    0 : <0x7d7> 
    1 : <0x2d> 
    2 : <0x20> 
    3 : <0x21> 
    4 : <0x1e> 
    5 : <0x9> 
    6 : <0x7a8> 
    7 : <0x2c> 
    8 : <0x2e> 
    9 : <0x743> 
    10 : <0x32> 
    11 : <0x85> 
    12 : <0x695> 
    13 : <0x62a> 
    14 : <0x62b> 
    15 : <0xa> 
    16 : <0x26> 
    17 : <0x18> 
    18 : <0x2> 
)} 
+0

ああ!さて、なぜそれがC配列のように半分、オブジェクトの半分のように振る舞っていたのかが分かります。答えをありがとう。 –

1

にNSArrayは、「フリーダイヤル架設されています"をCore Foundationの対応部 CFArrayリファレンスとともに使用しています。これが意味するのは、ブリッジタイプ のファンクションまたはメソッド呼び出しでCore Foundationタイプが であり、一方のタイプを他方のタイプにキャストするということです。 したがって、NSArray *パラメータを参照するAPIでは、 をCFArrayRefに渡し、APIでCFArrayRef パラメータを参照すると、NSArrayインスタンスを渡すことができます。この配列も NSArrayの具体的なサブクラスに適用されます。

したがって、問題は2つのメソッドを呼び出すことである必要があります。

現在のユーザーセッションのウィンドウの1についての情報 が含まれ、それぞれがCFDictionaryRefタイプの配列:ここでも、ドキュメント、CGWindowListCopyWindowInfoから値を返す持っています。目的の基準に一致する のウィンドウがない場合、この関数は空の 配列を返します。この関数をGUIセキュリティ セッションの外から呼び出した場合、またはウィンドウサーバーが実行されていない場合は、 NULLを返します。 CGWindowID値の配列が所望のウィンドウに対応

CGWindowListCreate戻り値を有しています。 目的の基準に一致するウィンドウがない場合、関数 は空の配列を返します。 GUIセキュリティセッションの外からこの関数を呼び出した場合、またはウィンドウサーバーが実行されていない場合、この 関数はNULLを返します。

NSLog(@"%@",array);に電話すると、descriptionというメッセージが配列の各オブジェクトに送信されます。フロート、BOOLおよびintはこのメッセージに応答しません。たとえば、

NSLog(@"Printing 2: %@",2); 

のエラーを取得しますが、エラーは、intコールを使用する場合消える:CGWindowListCreateCGWindowID値の配列を返して、あなたのケースのために

NSLog(@"Printing 2: %d",2); 

を、これらの32ビットの符号なし整数です。したがって、彼らは%@に応答しませんが、%uに応答します。したがって、修正は%uを使用して手動で配列を印刷することです。

+0

OK、私は 'のNSLog( "アレイ%ldの" @ [(__bridgeにNSArray *)カウントwindowIDList])試してみました;'と、それは14と 'CFArrayGetCount(windowIDListを返します。 ) 'を返し、14も返すが、NSLog(@" Array%@ "、[(__bridge NSArray *)windowIDList objectAtIndex:1]);はまだクラッシュします。 –

+1

それでは、 'CGWindowID'が' description'に応答しないという問題があります。これは、32ビットのunsigned intと思われる。 'NSLog(@" Array%u "、[(__bridge NSArray *)windowIDList objectAtIndex:0]); ' – PengOne

+0

これは動作しますが、私はそれを取得しません。 –