Подавление устаревших предупреждений в Xcode

133

Поскольку все SDK распространяются по всему миру, удобно иметь возможность создавать для нескольких SDK и платформ. Однако при переходе с 3.2 на 3.0 и даже иногда на 2.x я часто получаю устаревшие предупреждения о методах, которые были изменены или заменены:

warning: 'UIKeyboardBoundsUserInfoKey' is deprecated.

Поскольку я по-прежнему хочу поддерживать совместимость со старыми ОС, и я также стремлюсь удалить «шум» при сборке, есть ли способ отключить или отключить эти предупреждения?

Бен Готлиб
источник
4
Хотя ответ Пола Р. работает, учтите, что маникезар немного более хирургический, поскольку он позволяет вам подавить именно то предупреждение, которое вы хотите, без потери других дополнительных предупреждений, которые могут быть важны. Мне кажется, что с точки зрения лучших практик, у manicaesar есть The Correct Answer ™
Оли

Ответы:

82

Попробуйте -Wno-deprecated-declarationsили соответствующий ему параметр в Xcode GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS(совет от профессионала: просто введите «устаревшее» в настройках сборки, чтобы найти конкретный параметр для этого предупреждения).

Текущие версии Xcode (например, Xcode 9.2):

введите описание изображения здесь


Древние версии Xcode (например, Xcode 2.x, 3.x):

введите описание изображения здесь

Пол Р
источник
17
Оказывается, это даже проще; есть флажок в настройках цели Xcode; Ваш ответ побудил меня искать там. Спасибо!
Бен Готтлиб,
4
Вы также можете сделать это для каждого файла отдельно. См. Этот ответ для добавления флагов для каждого файла: stackoverflow.com/a/6658549/272473
mrwalker
4
такие ответы разочаровывают новичков. Попробовать где? Как мне найти настройки цели? Немного дополнительных объяснений повысит ценность этого ответа.
noogrub
8
Этот плохо объясненный ответ не следует отмечать как правильный.
Крис Хаттон
6
Найдите «Устарело» в настройках сборки, и вы его увидите.
Quantumpotato
337

Поскольку я пока не могу добавить комментарий к посту @samiq, думаю, что расширю его. Введите указанную директиву перед функцией / методом, в котором вы используете устаревший материал. Затем вы можете восстановить предыдущую настройку после определения функции end:

#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- (void) methodUsingDeprecatedStuff {
    //use deprecated stuff
}
#pragma GCC diagnostic pop
manicaesar
источник
1
Превосходно! Это то, что я искал +1 :)
Зоран Симич
1
Потрясающий совет! Жаль, что его нельзя объявить внутри метода.
Дастин
12
Фактически это можно объявить внутри метода. Я просто должен был сделать это сегодня из-за ошибки в docs / sdk
jer
6
+1 Немного лучше всего использовать синтаксис с так #pragma GCC diagnostics push #pragma GCC diagnostics ignored "-Wdeprecated-declarations" .. .. Code here .. .. #pragma GCC diagnostic pop как этот метод возвращает вас к тому , что установка была установлена до .. [ gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html]
Никлас
3
Изменено согласно предложениям :)
manicaesar
143

Clang предоставляет удобную функцию, которая делает шаг «восстановления» в сообщении @manicaesar независимым от начального состояния предупреждения:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void) methodUsingDeprecatedStuff {
    //use deprecated stuff
}
#pragma clang diagnostic pop

Цитирую Clang руководство :

В дополнение ко всем функциям, предоставляемым прагмой GCC, Clang также позволяет вам нажимать и выдавать текущее состояние предупреждения. Это особенно полезно при написании файла заголовка, который будет компилироваться другими людьми, потому что вы не знаете, с какими предупреждающими флагами они строят.

Эндрю Хершбергер
источник
1
В более поздних версиях GCC используется тот же синтаксис (замените GCC на clang).
Niclas
3
Я всегда не понимаю, что такое LLVM, GCC и Clang. Итак, я хотел оставить заметку, чтобы сэкономить время. GNU Complier Collection (GCC) использовался с Xcode 3, затем Apple выпустила Xcode 4 с гибридным LLVM-GCC. Затем на смену пришел компилятор виртуальных машин низкого уровня (LLVM), дополнительную информацию см . На сайте llvm.org . Начиная с Xcode 7.2.1 компилятором по умолчанию является Apple LLVM 7.0. Компилятор LLVM - это библиотека других «проектов», отладчиков и других инструментов, включая собственный компилятор Clang. Clang - это "родной для LLVM" компилятор C / C ++ / Objective-C.
serge-k
42

Поскольку нам, как правило, необходимо поддерживать старые ОС, но обратите внимание на наши предупреждения, мне нужен более аккуратный способ сделать это. Я собрал это вместе, вдохновленный некоторым кодом Mozilla:

#define SILENCE_DEPRECATION(expr)                                   \
do {                                                                \
_Pragma("clang diagnostic push")                                    \
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")   \
expr;                                                               \
_Pragma("clang diagnostic pop")                                     \
} while(0)

#define SILENCE_IOS7_DEPRECATION(expr) SILENCE_DEPRECATION(expr)
#define SILENCE_IOS8_DEPRECATION(expr) SILENCE_DEPRECATION(expr)

Это позволяет вам сделать следующее:

SILENCE_IOS7_DEPRECATION(return [self sizeWithFont:font constrainedToSize:size]);

Он также работает с блоками кода:

SILENCE_IOS7_DEPRECATION(
    view = [[MKPolylineView alloc] initWithPolyline:self];
    view.lineWidth = self.lineWidth;
    view.strokeColor = self.color;
);

Кроме того, когда вы отказываетесь от поддержки устройств до iOS 7, вы можете легко выполнить поиск по коду, чтобы найти устаревшие способы использования, которые нужно исправить.

Джо Хьюз
источник
это гораздо лучшее долгосрочное решение для большей части кода, чем ограничение предупреждений об устаревании (или любых других) на глобальном уровне / уровне проекта. потрясающий ответ.
natbro
1
Почему do { ... } while(0);требуется?
Ben Leggiero
1
@ BenC.R.Leggiero, потому что вы передаете не блок, а несколько операторов между этими скобками. Вы в основном подавляете предупреждения для каждой строки.
Алехандро Иван,
1
@ AlejandroIván Я знаю, что ваше объяснение имеет для вас смысл ... но мне кажется, что вы переформулируете вопрос. Вы можете объяснить, почему do{...}while(0);именно здесь требуется? Почему не просто {...}? Почему нет if(true){...}? и т.д.
Ben Leggiero
2
@ BenC.R.Leggiero, ты прав. Почему-то я неправильно понял ваш вопрос. Проверьте принятый ответ здесь: stackoverflow.com/questions/154136/…
Алехандро Иван,
29

Вы также можете подавить предупреждения для каждого файла, используя

#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

что, в свою очередь, делает это немного лучше, чем просто подавление всех предупреждений один раз и вместе ... в конце концов, вы должны знать, для чего вы это делаете.

samiq
источник
20

Если вы хотите отключить предупреждение « Реализация устаревшего метода» или « Реализация устаревшего класса» , используйте:

    #pragma clang диагностический push
    #pragma clang диагностика игнорируется "-Wdeprecated-implementationations"
    // код
    #pragma clang диагностический поп

Кшиштоф
источник
Когда я увидел «-Wdeprecated-декларации», я полагал, что должно быть «-Wdeprecated-implementationations». И это действительно работает. Спасибо.
DawnSong
8

В настройках сборки найдите Deprecated Functions.

введите описание изображения здесь

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

Если вам нужна полная проверка всех видов устаревших функций в фрагменте кода. Используйте флаг -Wdeprecated, как показано ниже:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
- (void) methodUsingDeprecatedStuff {
    //use deprecated stuff
}
#pragma clang diagnostic pop
jarora
источник
-3

Чтобы отключить предупреждение из стороннего файла заголовка, добавьте следующую строку вверху файла

#pragma clang system_header
harvestli
источник