2011-11-10 19 views
6

Esto está bien:Crash cuando se lanza CFArrayRef a NSArray

CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 
NSLog(@"%@", (__bridge NSArray *)windowList); 

Esto hace que EXC_BAD_ACCESS:

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

Respuesta

8

Las matrices creadas como NSArray s solo pueden contener elementos que actúan como objetos Objective-C.

Las matrices creadas como CFArray pueden contener cualquier cosa, si pasa el CFArrayCallBacks correspondiente al CFArrayCreate.

CGWindowListCreate está creando una CFArray, y llenarlo con cosas que no actúan como objetos, pero CGWindowListCreate está utilizando CFArrayCallbacks que no se preocupan por eso.

Cuando intenta imprimir esta CFArray con el %@ especificador de formato, NSLog envía un mensaje de Objective-C -description a la matriz. El CFArray maneja esto enviando un mensaje Objective-C description a cada uno de sus elementos. Desafortunadamente, sus elementos no son objetos y por lo tanto es imposible enviarles mensajes de Objective-C. Por lo tanto, el accidente.

Tal vez puedas probar:

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

La función CFCopyDescription utiliza uno de los CFArrayCallbacks funciones de cada elemento de la matriz, en lugar de intentar enviar un mensaje de Objective-C para cada uno. La devolución de llamada sabe cómo manejar el elemento de la matriz, por lo que funciona bien. Consigo este resultado en mi programa de pruebas:

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

¡Ah! Ahora eso tiene sentido en cuanto a por qué se comportaba como una matriz C y la mitad como un objeto. Gracias por la respuesta. –

1

Desde el documentation en NSArray:

NSArray es “puenteado de teléfono gratuito "Con su contraparte de Core Foundation, CFArray Reference. Lo que esto significa es que el tipo de Fundación básica es intercambiable en llamadas de función o método con el objeto de base puenteado , siempre que envíe un tipo al otro. Por lo tanto, en una API donde vea un parámetro NSArray *, puede pasar un CFArrayRef, y en una API donde vea un parámetro CFArrayRef , puede pasar una instancia de NSArray. Esta disposición también se aplica a sus subclases concretas de NSArray.

Así que el problema debe ser con los dos métodos que se llaman. Una vez más, desde la documentación, CGWindowListCopyWindowInfo tiene valor de retorno:

una matriz de tipos CFDictionaryRef, cada uno de los cuales contiene información acerca una de las ventanas de la sesión del usuario actual. Si no hay ventanas que coincidan con los criterios deseados, la función devuelve una matriz vacía. Si llama a esta función desde fuera de una sesión de seguridad de GUI o cuando no se está ejecutando ningún servidor de ventana, esta función devuelve NULL.

y CGWindowListCreate tiene valor de retorno:

Matriz de valores CGWindowID correspondiente a las ventanas deseadas. Si no hay ventanas que coincidan con los criterios deseados, la función devuelve una matriz vacía. Si llama a esta función desde fuera de una sesión de seguridad de GUI o cuando no se está ejecutando ningún servidor de ventana, esta función devuelve NULL.

Cuando se llama a NSLog(@"%@",array);, el mensaje description se envía a cada objeto de la matriz. Flotantes, BOOL y entradas no responden a este mensaje. Por ejemplo, obtendrá un error de

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

pero el error desaparece si se utiliza el int llamada:

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

Para su caso, CGWindowListCreate está volviendo una serie de CGWindowID valores, y estos son enteros sin signo de 32 bits. Por lo tanto, no responden a %@, pero responderán a %u. Por lo tanto, la solución es imprimir el arreglo manualmente usando %u.

+0

bien, me trató 'NSLog (@ "Matriz% ld", [(__bridge NSArray *) windowIDList cuenta]);' y devuelve 14 y 'CFArrayGetCount (windowIDList) 'y también devuelve 14, por lo que parece ser una matriz normal, pero' NSLog (@ "Array% @", [(__bridge NSArray *) windowIDList objectAtIndex: 1]); 'aún se bloquea. –

+1

Entonces el problema es que 'CGWindowID' no responde a' description'. Parece ser una int de 32 bits sin signo. Pruebe 'NSLog (@" Array% u ", [(__bridge NSArray *) windowIDList objectAtIndex: 0]);' – PengOne

+0

Funciona, pero no lo entiendo. –

Cuestiones relacionadas