Сбой при приведении CFArrayRef к NSArray - PullRequest
6 голосов
/ 11 ноября 2011

Это нормально:

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

Это вызывает EXC_BAD_ACCESS:

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

Ответы [ 2 ]

8 голосов
/ 11 ноября 2011

Массивы, созданные как NSArray s, могут содержать только элементы, которые действуют как объекты Objective-C.

Массивы, созданные как CFArray s, могут содержать все, что угодно, если вы передадите соответствующий CFArrayCallBacks CFArrayCreate.

CGWindowListCreate создаст CFArray и наполнит его вещами, которые неон действует как объекты, но CGWindowListCreate использует CFArrayCallbacks, который не заботится об этом.

Когда вы пытаетесь напечатать это CFArray с помощью спецификатора формата %@, NSLog отправляетObjective-C -description сообщение в массив.CFArray обрабатывает это, отправляя сообщение Objective-C description каждому из его элементов.К сожалению, его элементы не являются объектами, и поэтому отправлять им сообщения Objective-C невозможно.Таким образом, происходит сбой.

Попробуйте вместо этого:

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

Функция CFCopyDescription использует одну из CFArrayCallbacks функций для каждого элемента массива, вместо того, чтобы пытаться отправить Objective-С сообщением каждому.Обратный вызов знает, как обрабатывать элемент массива, поэтому он работает нормально.Я получаю этот вывод в моей тестовой программе:

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>
)}
1 голос
/ 11 ноября 2011

Из документации в NSArray:

NSArray «соединен бесплатно» со своим базовым аналогом, ссылкой CFArray.Это означает, что тип Core Foundation взаимозаменяем в вызовах функций или методов с мостовым объектом Foundation, предоставляя вам возможность приводить один тип к другому.Следовательно, в API, где вы видите параметр NSArray *, вы можете передать CFArrayRef, а в API, где вы видите параметр CFArrayRef, вы можете передать экземпляр NSArray.Это расположение также относится к вашим конкретным подклассам NSArray.

Таким образом, проблема должна быть с двумя вызываемыми методами.Опять же, из документации CGWindowListCopyWindowInfo имеет возвращаемое значение:

Массив типов CFDictionaryRef, каждый из которых содержит информацию об одном из окон в текущем сеансе пользователя.Если нет окон, соответствующих требуемым критериям, функция возвращает пустой массив.Если вы вызываете эту функцию вне сеанса безопасности графического интерфейса или когда не работает ни один оконный сервер, эта функция возвращает NULL.

и CGWindowListCreate имеет возвращаемое значение:

Массив значений CGWindowID, соответствующих желаемым окнам.Если нет окон, соответствующих требуемым критериям, функция возвращает пустой массив.Если вы вызываете эту функцию вне сеанса безопасности графического интерфейса или когда не работает ни один оконный сервер, эта функция возвращает NULL.

Когда вы вызываете NSLog(@"%@",array);, сообщение description отправляется каждомуОбъект в массиве.Float, BOOLs и int не отвечают на это сообщение.Например, вы получите ошибку для

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

, но ошибка исчезнет, ​​если вы используете вызов int:

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

В вашем случае CGWindowListCreate возвращаетмассив значений CGWindowID, и это 32-разрядные целые числа без знака.Поэтому они не отвечают на %@, но будут отвечать на %u.Следовательно, исправление состоит в том, чтобы печатать массив вручную, используя %u.

...