Використання виводу Swift 3 @objc у режимі Swift 4 застаріле?


485

Якщо коротко, використовуючи Xcode 9 Beta, я наткнувся на таке попередження:

Використання висновку Swift 3 @objc у режимі Swift 4 застаріле. Будь ласка, зверніться до застарілих попереджень @objc про висновки, протестуйте свій код із ввімкненим журналом "Використання застарілого Swift 3 @objc" і вимкніть Swift 3 @objc. **

Після деяких досліджень я досі не маю уявлення, як виправити проблему. Я дуже вдячний за будь-які поради щодо виправлення цього питання, а також пояснення того, що відбувається.

Моя мета - зрозуміти краще розуміння того, що відбувається з моїм кодом.


4
Я дійсно не отримую з попереджувального повідомлення, який об’єкт його викликає. Xcode просто не говорить, у якому рядку знаходиться цей об’єкт. Будь-які поради, як дізнатися, звідки береться це попередження?
олив

Відповіді:


816

Я позбувся цього попередження, змінивши налаштування збірки "Swift 3 @objc" моїх цілей на "За замовчуванням".

Вимкнути Swift 3 @objc умовивід у Xcode9

З цієї статті :

Перед Swift 4 компілятор зробив кілька оголошень Swift автоматично доступними для Objective-C . Наприклад, якщо один підклас від NSObject, компілятор створив точки введення Objective-C для всіх методів у таких класах. Механізм називається @objc умовивід.

У Swift 4 такий автоматичний висновок @objc застарілий, оскільки це дороге створення всіх цих вхідних точок Objective-C. Коли для параметра "Swift 3 @objc Inference" встановлено значення "Увімкнено", це дозволяє старому коду працювати. Однак він покаже попередження про недостатність, на які потрібно звернути увагу. Рекомендується "виправити" ці попередження та переключити налаштування на "За замовчуванням" , що є типовим для нових проектів Swift.

Для отримання додаткової інформації також зверніться до цієї пропозиції Swift .


5
Дякую, Євгеній. Це довгострокове рішення?
DaleK

6
@DaleK так, я так вірю. Згідно з пропозицією Swift, про яку я згадував у своїй відповіді, висновок objc застарілий. Налаштування "Swift 3 objc Inference" є лише у проектах, які були перенесені зі старих версій Swift. Якщо створюється новий проект, параметр більше не присутній, це означає, що висновок objc вимкнено. Рекомендується звертатися з будь-якими попередженнями щодо об'єкта і встановлювати його на "Вимкнено".
Євгеній

4
Інформаційне повідомлення в XCode говорить про те, що: "Використання @objcвисновку Swift 3 у режимі Swift 4 застаріле. Будь ласка, зверніться до застарілих @objcпопереджень про висновки, протестуйте свій код із @objcувімкненим журналом" Використання застарілого висновку Swift 3 " та відключіть @objcвисновок Swift 3. " Будь-яка ідея, де ввімкнути згаданий @objcвивід Swift 3 ?
куртюсельк

4
@courteouselk, згідно з пропозицією Swift, можна встановити SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT екологічну змінну до значень від 1 до 3, щоб побачити використання точок вводу Objective-C у журналах.
Євгеній

14
Просто додати - це потрібно зробити для всіх цілей збирання, а не лише для проекту.
Криввенз

270

- Що таке @objcумовивід? Що відбувається?

В Swift 3, в компілятор виводить @objcв ряді місць , так що ви не повинні. Іншими словами, це обов'язково додасть @objcвам!

У Swift 4, компілятор більше цього не робить (як багато). Тепер ви повинні додати @objcявно.

За замовчуванням, якщо у вас є проект попереднього Swift 4, ви отримаєте попередження про це. У проекті Swift 4 ви отримаєте помилки в побудові. Це контролюється через SWIFT_SWIFT3_OBJC_INFERENCEналаштування збірки. У попередньому проекті Swift 4 це встановлено на On. Я рекомендую встановити це значення Default(або Off), що зараз є параметром за замовчуванням для нового проекту.

Щоб конвертувати все, знадобиться деякий час, але оскільки це за замовчуванням для Swift 4, це варто зробити.

- Як зупинити попередження / помилки компілятора?

Існує два способи перетворення коду, щоб компілятор не скаржився.

Перший - використовувати @objcдля кожної функції або змінної, яку потрібно піддавати виконанню Objective-C:

@objc func foo() {

}

Інший полягає в використанні @objcMembersпо Classдекларації. Це гарантує автоматичне додавання @objcдо ВСІХ функцій та змінних у класі. Це простий спосіб, але він має вартість, наприклад, він може збільшити розмір вашої програми, відкривши функції, які не потребували впливу.

@objcMembers class Test {

}

- Що таке @objcі навіщо це потрібно?

Якщо ви вводите нові методи або змінні до класу Swift, позначаючи їх як @objcпіддають їх виконанню Objective-C. Це необхідно, якщо у вас є код Objective-C, який використовує ваш клас Swift, або, якщо ви використовуєте такі функції типу Objective-C Selectors. Наприклад, схема цільової дії: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Чому я б не відзначив усе @objc?

Є негативи, які позначають щось як @objc:

  • Збільшений розмір бінарних програм
  • Немає функцій перевантаження

Будь ласка, майте на увазі, що це резюме дуже високого рівня і що воно складніше, ніж я писав. Я рекомендую прочитати фактичну пропозицію для отримання додаткової інформації.

Джерела:


@objcне передбачає динамічної диспетчеризації, Swift вільний використовувати статичну або віртуальну диспетчеризацію (і, можливо, в результаті виконувати інший код). dynamicКлючовим слово потрібно , щоб змусити Swift використовувати динамічну диспетчеризацію.
кевін

7
Чи є інші способи додати дії до кнопки? Якщо нам @objcпридушено, що ми повинні використовувати?
Азнікс

5
@Stefan так, конвертувати може бути небагато. Розділіть його на етапи. Залиште SWIFT_SWIFT3_OBJC_INFERENCEна On. Перетворити на Swift 4. Потім вирішити цю @objcріч. Щоб зробити це просто, дотримуйтесь основних правил: Якщо клас Swift використовується в коді Objc-C (за допомогою мостового заголовка), використовуйте в @objcMembersіншому випадку додавання один за одним @objc. Просто використовуйте пошук Xcode, щоб дізнатися, чи викликається клас Swift з якого-небудь .mфайлу. Це повинно зробити перетворення відносно безболісним.
kgaidis

5
@DaleK на це слід прийняти відповідь. Придушення попереджень та примушення роботи так, як вони були у Swift 3 - це варіант, але IMHO - не найкращий. Важливо зрозуміти, чому @objcзмінився Swift 4, а потім прийняти рішення виправити проект і зберегти його таким же.
дерполюк

2
Дякую за це коротке пояснення
Шмоді

48

Мігратор не може ідентифікувати всі функції, які потребують @objc Inferred Objective-C грохотів, позначених як застарілі, щоб допомогти вам їх знайти
• Побудувати попередження про застарілі методи
• Повідомлення консолі під час запуску застарілих гронів

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


1
То що мені робити з @objc? видали це? Облиш це? Я це вже видалив. і я отримую ці попередження, тому я повинен їх додати? що на кроці 3 я повинен робити це?
Шиал

Додати @objc безпосередньо перед func
Хасан Талеб

1
про який крок 3 йдеться? Ви можете додати деякі описи :)
Шиал

І в моєму випадку я отримую це попередження, але жоден код не вказується. Є два методи, позначені @objc, і вони здаються єдиними, які потребують цього. Я змінив його на Типовий і досі отримую попередження під час компіляції.
Maury Markowitz

12

У мене було це попередження за допомогою параметра "Swift 3 @objc Inference" = "За замовчуванням". Тоді я зрозумів, що встановлено для Проекту - не для цілі. Отже, переконайтеся, що у вашій цілі встановлено "Типово", щоб позбутися від попередження.


Я витратив 20 хвилин, щоб вирішити помилку навіть після того, як я змінив налаштування проекту за замовчуванням. Ви точно вказали, що це потрібно також змінити в цілі.
SkrewEverything

8

Ви можете просто перейти до "за замовчуванням" замість "ВКЛ". Здається більш прихильним до логіки Apple.

(але всі інші коментарі щодо використання @objзалишаються дійсними.)


7

Дійсно, ви позбудетесь цих попереджень, відключивши Swift 3 @objc Inference. Однак тонкі проблеми можуть спливати. Наприклад, KVO перестане працювати. Цей код відмінно працював під Swift 3:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

Після переходу на Swift 4 та встановлення "Swift 3 @objc Inference" за замовчуванням деякі функції мого проекту перестали працювати . Мені знадобилися деякі налагодження та дослідження, щоб знайти рішення для цього. Наскільки мені відомо, ось такі варіанти:

  • Увімкніть "Swift 3 @objc Inference" (працює лише якщо ви перемістили існуючий проект із Swift 3) введіть тут опис зображення
  • Позначте порушені методи та властивості як @objc введіть тут опис зображення
  • Повторно увімкніть умовивід ObjC для всього класу за допомогою @objcMembers введіть тут опис зображення

Повторне включення @objc висновок залишає вас застереженнями, але це швидке рішення. Зауважте, що він доступний лише для проектів, переміщених із попередньої версії Swift. Інші два варіанти є більш втомливими і потребують певного кодування та обширного тестування.

Дивіться також https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md


7

Я час від часу розробник iOS (незабаром стане більше), але я все ще не міг знайти налаштування, як керувався іншою відповіддю (оскільки у мене не було цього елемента брелка, який показує відповідь), тому тепер, коли знайшов це, я подумав Я можу просто додати цей знімок із виділеними місцями, які вам потрібно буде натиснути та знайти.

  1. Почніть з лівого верхнього кута
  2. Виберіть значок папки проекту
  3. Виберіть основну назву проекту під значком папки проекту.
  4. Виберіть Налаштування побудови праворуч.
  5. Виберіть проект у розділі TARGETS.
  6. Прокрутіть дуже далеко вниз (або шукайте умовивід слова в текстовому полі пошуку)

Пошук налаштування


6

Ви можете спробувати "Поновити оновлення" та / або "трепетно ​​очистити"

Я також встановив цей параметр у xcode.

Параметр інтерфейсу Objective-C такий:

Налаштування інтерфейсу ObjectiveC


2

Swift 3 @objc Висновок Використання висновку Swift 3 @objc в режимі Swift 4 застаріле. Будь ласка, зверніться до застарілих попереджень @objc про висновки, протестуйте свій код із ввімкненим журналом "Використання застарілого Swift 3 @objc", а потім вимкніть висновок, змінивши налаштування збірки "Swift 3 @objc" на "За замовчуванням" для "XMLParsingURL" цільовий.

дісталися до

  1. Перший крок отримав Налаштування збірки

  2. Шукайте, щоб створити умовиводи

  3. змінити swift 3 @objc Висновок за замовчуванням

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


1

Все, що вам потрібно, просто запустіть тестовий зачекання до кінця, після цього перейдіть до "Налаштування збірки", знайдіть в "Налаштування параметрів побудови", змініть швидкий 3 @objc Inference на (За замовчуванням). це все, що я робив і працював ідеально.


0

Використання виводу Swift 3 @objc у режимі Swift 4 застаріле?

використовувати функцію call @objc

func call(){

foo()

}

@objc func foo() {

}

0

Крім того, що сказав @wisekiddo, ви також можете змінити налаштування збирання у project.pbxprojфайлі, встановивши Swift 3 @obj Inference за замовчуванням, як SWIFT_SWIFT3_OBJC_INFERENCE = Default;для ваших ароматів збірки (тобто налагодження та випуск), особливо якщо ви надходите з іншого середовища крім Xcode

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.