Подавление «…» не рекомендуется »при использовании responsedsToSelector - PullRequest
55 голосов
/ 14 декабря 2009

Я поддерживаю 10.4+, выбирая самый последний API во время выполнения:

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)])
    [fileManager removeItemAtPath:downloadDir error:NULL];
else
    [fileManager removeFileAtPath:downloadDir handler:nil];

В этом случае для 10.5 и выше будет использоваться removeItemAtPath:error:, а для 10.4 будет использоваться removeFileAtPath:handler:. Отлично, но я все еще получаю предупреждения компилятора для старых методов:

warning: 'removeFileAtPath:handler:' is deprecated [-Wdeprecated-declarations]

Существует ли синтаксис if([… respondsToSelector:@selector(…)]){ … } else { … }, который намекает компилятору (Clang) не предупреждать в этой строке?

Если нет, есть ли способ пометить эту строку, чтобы ее игнорировали для -Wdeprecated-declarations?


Посмотрев некоторые ответы, позвольте мне уточнить, что путать компилятор с тем, что он не знает, что я делаю, не является правильным решением.

Ответы [ 5 ]

115 голосов
/ 14 декабря 2009

Я нашел пример в Руководстве пользователя Clang Compiler, который позволяет мне игнорировать предупреждение:

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)]) {
    [fileManager removeItemAtPath:downloadDir error:NULL];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    [fileManager removeFileAtPath:downloadDir handler:nil];
#pragma clang diagnostic pop
}
8 голосов
/ 14 декабря 2009

Вы можете объявить отдельный файл, который предназначен для вызова устаревших методов, и установить флаги компилятора для каждого файла в XCode, чтобы игнорировать -Wdeprecated-declarations. Затем вы можете определить в этом файле фиктивную функцию для вызова устаревших методов и тем самым избежать предупреждений в ваших реальных исходных файлах.

6 голосов
/ 14 декабря 2009

Я не уверен, что clang достаточно умен, чтобы поймать это, но если это не так, вы можете попробовать использовать performSelector:withObject:withObject: или создать и вызвать объект NSInvocation.

5 голосов
/ 14 декабря 2009

Вы можете просто привести fileManager к id - ids, способному ссылаться на любой объект Objective-C, поэтому компилятор не должен проверять методы, которые вызываются для одного:

[(id)fileManager removeItemAtPath:downloadDir error:NULL];

не должен выдавать какие-либо предупреждения или ошибки.

Конечно, это вызывает другие проблемы, а именно, вы теряете все проверку во время компиляции дляметоды, вызываемые на id.Поэтому, если вы неправильно напишите имя метода и т. Д., Оно не будет перехвачено до тех пор, пока не будет выполнена эта строка кода.

3 голосов
/ 15 декабря 2009

Если вы считаете, что любая форма «путаницы» компилятора является неверным решением, вам, вероятно, придется смириться с предупреждением. (В моей книге, если вы спрашиваете, как избавиться от предупреждения, неразумно смотреть дареному коню в рот и говорить, что что-то недопустимо только потому, что это не выглядит так, как вы ожидаете.)

Ответы, которые работают во время выполнения, включают маскирование операции, которая происходит с динамической диспетчеризацией, чтобы компилятор не жаловался на устаревший вызов. Если вам не нравится такой подход, вы можете отключить «Предупреждать об устаревших функциях» в вашем проекте Xcode или в настройках цели, но это, как правило, плохая идея. Вы хотите знать об устаревших API, но в этом случае вы хотите использовать его без предупреждения. Существуют простые и трудные способы сделать это, и есть вероятность, что вы в любой форме сочтете их всех «недействительными», но это не мешает им быть эффективными, даже правильными. ; -)

Один из возможных способов избежать предупреждений, которые все еще выбираются во время выполнения, - это использовать objc_msgSend() напрямую:

objc_msgSend(fileManager, @selector(removeFileAtPath:error:), downloadDir, nil];

Это то, что среда выполнения Objective C делает под прикрытием в любом случае , и должна достичь желаемого результата с минимумом суеты. Вы можете даже оставить исходную строку с комментариями над ней для ясности. Я знаю, что в документации написано: «Компилятор генерирует вызовы для функции обмена сообщениями. Никогда не вызывайте ее напрямую в коде, который вы пишете». Вы сами должны решить, когда можно нарушать правила.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...