Подавление "..." устарело "при использовании responsesToSelector
Я поддерживаю 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
?
После просмотра некоторых из ответов позвольте мне пояснить, что запутать компилятор в неведении о том, что я делаю, не является допустимым решением.
Ответы
Ответ 1
Я нашел пример в Руководстве пользователя компилятора Clang, который позволяет мне игнорировать предупреждение:
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
}
Ответ 2
Вы можете объявить отдельный файл, предназначенный для вызова устаревших методов, и установить флаги компилятора для каждого файла в Xcode, чтобы игнорировать -Wdeprecated-declarations
. Затем вы можете определить фиктивную функцию в этом файле для вызова устаревших методов и тем самым избежать предупреждений в ваших реальных исходных файлах.
Ответ 3
Я не уверен, что clang достаточно умен, чтобы поймать это, но если это не так, вы можете попробовать использовать performSelector:withObject:withObject:
или создать и вызвать объект NSInvocation.
Ответ 4
Вы можете просто отличить fileManager
до id
- ids
, чтобы ссылаться на любой объект Objective-C, поэтому компилятор не должен проверять методы, которые вызывают один:
[(id)fileManager removeItemAtPath:downloadDir error:NULL];
не должно вызывать никаких предупреждений или ошибок.
Конечно, это вызывает другие проблемы, а именно: вы теряете всю проверку времени компиляции для методов, называемых id
. Поэтому, если вы пропустили имя метода и т.д., Его не поймают до тех пор, пока эта строка кода не будет выполнена.
Ответ 5
Если вы считаете, что какая-либо форма "запутывания" компилятора является недействительным решением, вам, вероятно, придется жить с предупреждением. (В моей книге, если вы спрашиваете, как избавиться от предупреждения, неразумно выглядеть подарочной лошадью во рту и сказать, что что-то недействительно, потому что оно не похоже на то, что вы ожидаете.)
Ответы, которые работают во время выполнения, включают маскирование операции, которая происходит с динамической отправкой, поэтому компилятор не жалуется на устаревший вызов. Если вам не нравится этот подход, вы можете отключить "Предупреждать о устаревших функциях" в вашем проекте или целевых настройках Xcode, но это, как правило, плохая идея. Вы хотите знать об устаревших API, но в этом случае вы хотите использовать его без предупреждения. Есть простые и трудные способы сделать это, и вероятность того, что вы считаете их "недействительными" в той или иной форме, но это не мешает им быть эффективными, даже правильными.; -)
Один из возможных способов избежать предупреждений, все еще выбранных во время выполнения, заключается в непосредственном использовании objc_msgSend()
:
objc_msgSend(fileManager, @selector(removeFileAtPath:error:), downloadDir, nil];
Это то, что среда выполнения Objective-C делает под обложками в любом случае, и должна выполнить результат, который вы хотите, с минимальным количеством суеты. Вы можете даже оставить исходную строку, прокомментированную выше, для ясности. Я знаю, что в документации говорится: "Компилятор генерирует вызовы функции обмена сообщениями. Вы никогда не должны называть его непосредственно в коде, который вы пишете". Вы сами должны решить, когда все в порядке, чтобы согнуть правила.