2014-12-04 4 views
0

Я использую метод Core Foundations, который я заимствовал из полезного приложения UIElementUtilities от Apple. Проблема в том, что я хочу обновить этот заимствованный метод, чтобы он работал под новой автоматической системой подсчета ссылок (ARC) Apple. Я сделал некоторый прогресс, адаптирующий большинство моих заимствованных методов, вставив квалификатор '__bridge' перед переменными, однако с помощью метода, показанного ниже, я получаю следующую ошибку после попытки конвертировать в ARC: «ошибка: несовместимые типы кастинг» NSString __strong * to 'CFTypeRef *' (aka 'const void **) с лирикой __bridge. Как сделать допустимый указатель на буфер «actionDescription», чтобы его содержимое было переработано в NSString?ARC Несовместимые типы литья

+ (NSString *)descriptionOfAction:(NSString *)actionName ofUIElement:(AXUIElementRef)element { 

NSString * actionDescription = nil; 

AXUIElementCopyActionDescription(element, (__bridge CFStringRef)actionName, (__bridge CFStringRef *)&actionDescription); 

return actionDescription; 

//return [actionDescription autorelease]; 

}

ответ

1

Интересный вопрос.

В ARC, когда вы назначаете ссылку на переменную, ARC должна знать, что делать с предыдущим значением переменной. Если переменная равна __strong, тогда старая ссылка должна быть отпущена, если она равна __unsafe_unretained, она может просто отказаться от старой ссылки и т. Д. Все это происходит в большинстве случаев, без необходимости беспокоиться.

Когда вы передаете указатель на переменную, содержащую ссылку, она становится немного более сложной, ARC должен знать квалификатор на заостренной переменной. Objective-C использует метод, называемый pass-by-writeback, который может включать использование скрытых временных переменных, чтобы убедиться, что все работает правильно, подробности см. В Objective-C Automatic Reference Counting. У Core Foundation нет эквивалента этого, и это то, что отключает ваше преобразование.

Решение состоит в том, чтобы передать функции указатель на ядра Foundation набранный переменной, а затем с переходом на Objective-C и ARC после вызова:

+ (NSString *)descriptionOfAction:(NSString *)actionName ofUIElement:(AXUIElementRef)element 
{ 
    CFStringRef actionDescription = nil; 

    AXUIElementCopyActionDescription(element, (__bridge CFStringRef)actionName, &actionDescription); 

    return (__bridge_transfer NSString *)actionDescription; 
} 

Обратите внимание на использование __bridge_transfer - The Copy в имя функции указывает, что возвращенный CFStringRef принадлежит абоненту и должен быть освобожден после использования, __bridge_transfer руки, принадлежащие ARC, которые затем будут ответственны за освобождение ссылки.

HTH

+0

Благодарим за решение и объяснение, однако очевидно, что я нахожусь над моей головой. – Antony

Смежные вопросы