Нужно ли импортировать заголовки файлов в языке swift

Обновлено: 04.07.2024

Я пытаюсь импортировать myFramework в проект. Я добавил myFramework в "Фазы сборки" -> "Связать двоичный файл с библиотеками".

Но в Swift я получаю ошибку No such module myFramework :

Импорт внешних платформ

Вы можете импортировать внешние фреймворки с чистой кодовой базой Objective-C, чистой кодовой базой Swift или смешанной кодовой базой. Процесс импорта внешней платформы одинаков, независимо от того, написана ли платформа на одном языке или содержит файлы на обоих языках. При импорте внешней платформы убедитесь, что для параметра сборки Defines Module для импортируемой платформы установлено значение Yes.

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

SWIFT

Вы можете импортировать фреймворк в любой файл Objective-C .m в другом целевом объекте, используя следующий синтаксис:

OBJECTIVE-C

Я создал myFramework с помощью Xcode 5. Xcode 5 не имеет настройки сборки «Определяет модуль».

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

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

Однако ваша структура написана на Objective-C. Итак, что вам нужно сделать, это импортировать классы, обращенные к Swift, в свой заголовок моста, как описано здесь.

Обратите внимание, что это не имеет ничего общего с импортом модуля в Swift. Директива import в файле заголовка моста просто уведомляет компилятор о необходимости «перевести» файлы заголовков Objective-C в синтаксис Swift и делает общедоступный заголовок видимым для Swift.

Итак, что вам теперь делать?

Сначала импортируйте файлы заголовков, которые вас интересуют, в заголовок моста. Вам нужно только импортировать заголовки, с которыми вы будете взаимодействовать в Swift.

Попробуйте скомпилировать свой проект на этом этапе. Если XCode не может найти файлы заголовков фреймворка, ваша проблема, вероятно, связана не со Swift или XCode 6, а с проблемой включения фреймворков в целом.

Надеюсь это поможет.

В Swift:

Запустите Xcode -> Создайте новый проект Xcode -> iOS -> Платформа и библиотека -> Какао Touch Framework -> Назовите структуру (например, sampleCocoaFramework) -> Создать.

Задайте цель -> Общие -> Информация о развертывании -> Цель развертывания.

Добавьте публичный класс: File -> New File -> iOS -> Swift File -> Назовите его (например, openCocoaClass) -> Create.

Теперь добавьте код в openCocoaClass.swift.

Очистите проект: Продукт -> Очистить

Настройте параметры схемы: Продукт -> Схема -> Изменить схему -> Выполнить -> Конфигурация сборки -> Выпуск.

Соберите фреймворк: Продукт -> Сборка.

Добавление платформы в проект: -

Запустите проект Xcode и назовите его (например, CocoaFrameworkTest).

Перетащите файл sampleCocoaFramework.framework в папку проекта CocoaFrameworkTest.

Цель -> Общие -> Вставить двоичные файлы -> Добавить другие -> Выбрать платформу -> Копировать элементы, если необходимо -> Готово.

Доступ к платформе в ViewController: -

Кроме того, убедитесь, что для параметра сборки «Определяет модуль» в разделе «Упаковка» установлено значение «Да».

Вам нужно в вашей цели c создать общедоступный заголовок с тем же именем, что и ваше приложение, в случае FrameworkName.h и добавить все классы, которые вы хотите предоставить (эти классы должны быть добавлены как общедоступный заголовок в свойствах проекта). для этого вы добавляете фреймворк и добавляете ссылку на свой общедоступный заголовок импорта FrameworkName

Вы можете импортировать внешнюю структуру objC в проект Swift, используя синтаксис ниже:

Хорошо, сейчас это Xcode 7.2. И я заметил, что быстрый импорт чувствителен к регистру. Пример - import uikit не будет работать. Вам нужно будет ввести его как import UIKit .

Только мои два цента.

Defines Module(DEFINES_MODULE) [About] создает .modulemap [About] для использования Modular Framework из Objective-C ( @import ) или Swift ( import )

Просто c ommand+B поможет!

Почему: Добавление фреймворка через Cocoapods создаст еще один проект модуля с необходимыми фреймворками в нем. Чтобы основной проект мог идентифицировать фреймворки, статические библиотеки обоих проектов должны быть соединены мостом. Для этого необходимо создать рабочее пространство.


Разработчик

Используя Swift с какао и Objective C


iBook

  • Обзор смешивания и подгонки
  • Импорт кода из того же приложения Target
  • Импорт кода из той же платформы Target
  • Импорт внешних платформ
  • Используя Swift от Objective C
  • Именование Вашего модуля продукта
  • Советы по устранению неисправностей и напоминания

Swift и Objective C в том же проекте

Совместимость Swift с Objective C позволяет Вам создать проект, содержащий файлы, записанные на любом языке. Можно использовать эту функцию, названную смешиванием и подгонкой, для записи приложений, имеющих кодовую базу на разных языках. Используя смешивание и подгонку, можно реализовать часть функциональности приложения, использующей последние функции Swift, и беспрепятственно включить его назад в существующую кодовую базу Objective C.

Обзор смешивания и подгонки

Objective C и файлы Swift могут сосуществовать в единственном проекте, был ли проект первоначально проект Swift или Objective C. Можно просто добавить файл другого языка непосредственно к существующему проекту. Этот естественный поток операций делает создающее приложение на разных языках и цели платформы столь же прямыми как создание приложения или цели платформы записанный на единственном языке.

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

image: ../Art/DAG_2x.jpg

Импорт кода из того же приложения Target

Если Вы пишете приложение на разных языках, Вы, возможно, должны получить доступ к своему коду Objective C от Swift и своему Коду SWIFT от Objective C. Процесс, описанный в этом разделе, применяется к целям неплатформы.

Импорт Objective C в Swift

Для импорта ряда файлов Objective C в том же приложении предназначаются как Код SWIFT, Вы полагаетесь на заголовок образования моста Objective C для представления тех файлов Swift. Когда Вы добавляете файл Swift к существующему приложению Objective C или файл Objective C к существующему приложению Swift, XCode предлагает создавать этот заголовочный файл.

image: ../Art/bridgingheader_2x.jpg

Если Вы принимаете, XCode создает заголовочный файл вместе с файлом, который Вы создавали, и называет его Вашим именем модуля продукта сопровождаемым путем добавления "-Bridging-Header.h" . (Вы узнаете больше об имени модуля продукта позже в Именовании Вашего Модуля продукта .)

Также можно создать образующий мост заголовок сами путем выбора File> New> File> (iOS или OS X)> Источник> Заголовочный файл.

Необходимо будет отредактировать образующий мост заголовочный файл для представления кода Objective C Коду SWIFT.

Импортировать код Objective C в Swift от той же цели

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

При Настройках Сборки удостоверьтесь Objective C, Соединяющий установку сборки Заголовка мостом под Swift Компилятор - Генерация кода имеет путь к заголовку.

Путь должен быть относительно Вашего проекта, подобного способу, которым Ваш путь Info.plist указан в Настройках Сборки. В большинстве случаев Вы не должны должны быть изменять эту установку.

Любые общедоступные заголовки Objective C, перечисленные в этом заголовочном файле образования моста, будут видимы к Swift. Функциональность Objective C будет доступна в любом файле Swift в той цели автоматически без любых операторов импорта. Используйте свой пользовательский код Objective C с тем же синтаксисом Swift, который Вы используете с системными классами.

  • let myCell = XYZCustomCell ()
  • myCell . subtitle = "A custom cell"

Импорт Swift в Objective C

При импорте Кода SWIFT в Objective C Вы полагаетесь на сгенерированный XCode заголовочный файл для представления тех файлов Objective C. Этот автоматически сгенерированный файл является заголовком Objective C, объявляющим интерфейсы Swift в Вашей цели. Это может считаться заголовком зонтика для Вашего Кода SWIFT. Имя этого заголовка является Вашим именем модуля продукта, сопровождаемым путем добавления "-Swift.h" . (Вы узнаете больше об имени модуля продукта позже в Именовании Вашего Модуля продукта .)

По умолчанию сгенерированный заголовок содержит интерфейсы для объявлений Swift, отмеченных с public модификатор. Это также содержит отмеченных с internal модификатор, если Ваша цель приложения имеет заголовок образования моста Objective C. Объявления, отмеченные с private модификатор не появляется в сгенерированном заголовке. Частные объявления не представлены Objective C, если они явно не отмечены с @IBAction , @IBOutlet , или @objc также. Для получения дополнительной информации о модификаторах уровня доступа посмотрите Управление доступом в Swift Язык программирования.

Вы не должны делать, что-либо специальное для создания сгенерированного заголовочного файла — просто импортирует его для использования его содержания в коде Objective C. Обратите внимание на то, что интерфейсы Swift в сгенерированном заголовке включают ссылки на все типы Objective C, используемые в них. При использовании собственных типов Objective C в Коде SWIFT удостоверьтесь, что импортировали заголовки Objective C для тех типов прежде, чем импортировать сгенерированный заголовок Swift в Objective C .m файл Вы хотите получить доступ к Коду SWIFT от.

Импортировать Код SWIFT в Objective C от той же цели

Импортируйте Код SWIFT из той цели в любой Objective C .m файл в той цели с помощью этого синтаксиса и заменяя надлежащим именем:

Файлы Swift в Вашей цели будут видимы в Objective C .m файлы, содержащие этого оператора импорта. Для получения информации об использовании Swift от кода Objective C посмотрите Используя Swift от Objective C .

Импорт в Objective C

Никакой оператор импорта

Код Objective C

Никакой оператор импорта; заголовок образования моста Objective C требуется

Импорт кода из той же платформы Target

Если Вы пишете платформу на разных языках, Вы, возможно, должны получить доступ к своему коду Objective C от Swift и своему Коду SWIFT от Objective C.

Импорт Objective C в Swift

Для импорта ряда файлов Objective C в той же платформе предназначаются как Код SWIFT, необходимо будет импортировать те файлы в заголовок зонтика Objective C для платформы.

Импортировать код Objective C в Swift от той же платформы

При Настройках Сборки, в Упаковке, удостоверяются, что установка Defines Module для той цели платформы установлена в Да.

В Вашем заголовочном файле зонтика импортируйте каждый заголовок Objective C, который Вы хотите представить Swift. Например:

Свифт будет видеть каждый заголовок, который Вы представляете публично в Вашем заголовке зонтика. Содержание файлов Objective C в той платформе будет доступно в любом файле Свифта в той цели платформы автоматически без любых операторов импорта. Используйте свой пользовательский код Objective C с тем же синтаксисом Свифта, который Вы используете с системными классами.

  • let myCell = XYZCustomCell ()
  • myCell . subtitle = "A custom cell"

Импорт Swift в Objective C

Для импорта ряда файлов Swift в той же платформе предназначаются как код Objective C, Вы ничего не должны импортировать в заголовок зонтика для платформы. Вместо этого импортируйте сгенерированный XCode заголовочный файл для своего Кода SWIFT в любой Objective C .m файл Вы хотите использовать свой Код SWIFT от.

Поскольку сгенерированный заголовок для цели платформы является частью открытого интерфейса платформы, только объявления, отмеченные с public модификатор появляется в сгенерированном заголовке для цели платформы. Можно все еще использовать методы Swift и свойства, отмеченные с internal модификатор из части Objective C Вашей платформы, поскольку долго они объявляются в классе, наследовавшемся от класса Objective C. Для получения дополнительной информации о модификаторах уровня доступа посмотрите Управление доступом в Swift Язык программирования.

Импортировать Код SWIFT в Objective C от той же платформы

При Настройках Сборки, в Упаковке, удостоверяются, что установка Defines Module для той цели платформы установлена в Да.

Импортируйте Код SWIFT из той цели платформы в любой Objective C .m файл в той цели платформы, использующей этот синтаксис и заменяющей надлежащими именами:

Файлы Swift в Вашей цели платформы будут видимы в Objective C .m файлы, содержащие этого оператора импорта. Для получения информации об использовании Swift от кода Objective C посмотрите Используя Swift от Objective C .

Импорт в Objective C

Никакой оператор импорта

Код Objective C

Никакой оператор импорта; заголовок зонтика Objective C требуется

Импорт внешних платформ

Можно импортировать внешние платформы, имеющие чистую кодовую базу Objective C, чистую кодовую базу Swift или кодовую базу на разных языках. Процесс для импорта внешней платформы является тем же, записана ли платформа на единственном языке или содержит файлы с обоих языков. То, когда Вы импортируете внешнюю платформу, удостоверьтесь, Определяет установку сборки Модуля для платформы, которую Вы импортируете, установлен в Да.

Можно импортировать платформу в любой файл Swift в различной цели с помощью следующего синтаксиса:

Можно импортировать платформу в любой Objective C .m файл в различной цели с помощью следующего синтаксиса:

Импорт в Objective C

Любая платформа языка

Используя Swift от Objective C

Как только Вы импортируете свой Код SWIFT в Objective C, используйте регулярный синтаксис Objective C для работы с классами Swift.

  • MySwiftClass * swiftObject = [[ MySwiftClass alloc ] init ];
  • [ swiftObject swiftMethod ];

Класс Swift или протокол должны быть отмечены с @objc атрибут, чтобы быть доступным и применимым в Objective C. Этот атрибут говорит компилятору, что к этой части Кода SWIFT можно получить доступ от Objective C. Если Ваш класс Swift является потомком класса Objective C, компилятор автоматически добавляет @objc атрибут для Вас. Для получения дополнительной информации посмотрите Swift Соответствие типов .

У Вас будет доступ к чему-либо в классе или протоколе, это отмечено с @objc припишите, пока это совместимо с Objective C. Это исключает функции только для Swift, такие как перечисленные здесь:

Перечисления определяются в Swift

Структуры определяются в Swift

Функции, определяемые верхнего уровня в Swift

Глобальные переменные определяются в Swift

Typealiases определяется в Swift

Стиль Swift variadics

Функции с приправой карри

Например, метод, берущий универсальный тип в качестве параметра или возвращающий кортеж, не будет применим от Objective C.

Для предотвращения циклических ссылок не импортируйте Swift в заголовочный файл Objective C. Вместо этого можно передать, объявляют, что класс Swift использует его в заголовке Objective C. Обратите внимание на то, что Вы не можете разделить класс Swift на подклассы в Objective C.

Ссылаться на класс Swift в заголовочном файле Objective C

  • // MyObjcClass.h
  • @class MySwiftClass ;
  • @interface MyObjcClass : NSObject
  • - ( MySwiftClass * ) returnSwiftObject ;
  • /* . */
  • @end

Именование Вашего модуля продукта

Имя сгенерированного XCode заголовка для Кода SWIFT и имя заголовка образования моста Objective C, который XCode создает для Вас, сгенерированы с Вашего имени модуля продукта. По умолчанию Ваше имя модуля продукта совпадает с Вашим названием продукта. Однако, если Ваше название продукта имеет какие-либо неалфавитно-цифровые символы, такие как период ( . ), они заменяются подчеркиванием ( _ ) на Ваше имя модуля продукта. Если имя начинается с числа, первое число заменяется подчеркиванием.

Можно также обеспечить пользовательское имя для имени модуля продукта, и XCode будет использовать это при именовании образования моста и сгенерированных заголовков. Чтобы сделать это, измените настройки сборки Имени Модуля продукта.

Советы по устранению неисправностей и напоминания

Обработайте свой Swift и файлы Objective C как тот же набор кода, и не упустите именование коллизий.

Если Вы работаете с платформами, удостоверьтесь, Определяет установку сборки Модуля при Упаковке, установлен в Да.

Если Вы работаете с заголовком образования моста Objective C, удостоверьтесь Objective C, Соединяющий установку сборки Заголовка мостом под Swift Компилятор - Генерация кода имеет путь к заголовку, который это относительно Вашего проекта. Путь должен быть непосредственно к самому файлу, не только к каталогу, в котором это находится.

XCode использует Ваше имя модуля продукта — не Ваше целевое имя — при именовании заголовка образования моста Objective C и сгенерированного заголовка для Кода SWIFT. Для получения информации об именовании модуля продукта посмотрите Именование Вашего Модуля продукта .

Чтобы быть доступным и применимым в Objective C, класс Swift должен быть потомком класса Objective C, или это должно быть отмечено @objc .

При обеспечении Кода SWIFT в Objective C помните, что Objective C не будет в состоянии перевести определенные функции, которые являются определенными для Swift. Для списка посмотрите Используя Swift от Objective C .

При использовании собственных типов Objective C в Коде SWIFT удостоверьтесь, что импортировали заголовки Objective C для тех типов прежде, чем импортировать сгенерированный заголовок Swift в Objective C .m файл Вы хотите использовать свой Код SWIFT от.

Объявления Swift, отмеченные с private модификатор не появляется в сгенерированном заголовке. Частные объявления не представлены Objective C, если они явно не отмечены с @IBAction , @IBOutlet , или @objc также.

Для целей приложения, объявления, отмеченные с internal если цель приложения имеет заголовок образования моста Objective C, модификатор появляется в сгенерированном заголовке.

Для целей платформы, только объявления с public модификатор появляется в сгенерированном заголовке. Можно все еще использовать методы Swift и свойства, отмеченные с internal модификатор из части Objective C Вашей платформы, поскольку долго они объявляются в классе, наследовавшемся от класса Objective C. Для получения дополнительной информации о модификаторах уровня доступа посмотрите Управление доступом в Swift Язык программирования.

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

Последнее обновление – февраль 2019 г.

TL;DR. Чтобы использовать «Swift»-код внутри «Objective-C» придется поступиться некоторыми «фичами» «Swift» и написать обертку над кодом, которая не будет использовать несовместимые с «Objective-C»-приемы («structures», «generics», «enum associated values», «protocol extensions» и пр.), а будет основываться на классах-наследниках NSObject .

Начало

Итак, у нас имеется «Objective-C»-проект и некий код на «Swift», который мы хотим использовать в этом проекте. Для примера, пусть это будет сторонний «Swift»-фреймфорк, который мы добавляем в проект, скажем, с помощью «CocoaPods». Как обычно, добавляем нужную зависимость в «Podfile», выполняем pod install , открываем «xcworkspace»-файл.

Чтобы импортировать фреймворк в «Objective-C»-файл не нужно ни прописывать import всего фреймворка, как мы привыкли это делать в «Swift», ни пытаться импортировать отдельные файлы публичных API фреймворка, как мы привыкли это делать в «Objective-C». В любой файл, в котором нам необходим доступ к функционалу фреймворка, мы импортируем файл с названием <НазваниеПроекта>-Swift.h – это автоматически сгенерированный заголовочный файл, который является проводником «Objective-C»-файлов к публичным «API», содержащимся в импортированных «Swift»-файлах. Выглядит это примерно так:

Использование «Swift»-классов в «Objective-C»-файлах

Если вам удалось после импорта «Swift»-заголовка просто использовать какой-либо его класс или метод в «Objective-C»-проекте, вам крупно повезло – значит, кто-то до вас позаботися о совместимности. Дело в том, что «Objective-C» «переваривает» только классы-потомки NSObject и видит только публичные «API». А внутри классов нужные публичные свойства, инициализаторы и методы должны быть аннотированы @objc .

Если мы импортируем свой собственный «Swift»-код, то у нас, конечно, есть возможность в нем и «отнаследоваться» от чего угодно, и аннотацию (или атрибут) @objc добавить. Но в таком случае, наверное, у нас есть возможность и нужный код написать на «Objective-C». Поэтому больший смысл имеет сосредоточиться на случае, когда мы хотим импортировать чужой «Swift»-код в свой проект. В этом случае, скорее всего, у нас нет возможности добавить в нужные классы ни какое-либо наследование, ни прочее. Что делать в таком случае? Остается писать обертки!

Предположим, импортируемый фреймворк содержит следующий нужный нам класс:

Мы создаем свой «Swift»-файл, импортируем в него внешний фреймворк, создаем свой класс, отнаследованный от NSObject , а в нем объявляем приватный член типа внешнего класса. Чтобы иметь возможность вызывать методы внешнего класса, мы определяем методы в нашем классе, которые внутри себя будут вызывать соответствующие методы внешнего класса через приватный член класса (звучит запутанно, но по коду, думаю, все понятно):

(Доступ к классу NSObject и аннотации @objc появляется после импорта Foundation.)

По понятным причинам мы не можем использовать те же имена классов и методов в объявлениях. И здесь нам приходит на помощь аннотация @objc :

Теперь при вызове из «Objective-C»-кода названия классов и методов будут выглядеть именно так, какими мы хотели бы их видеть – как будто мы пишем соответствующие названия из внешнего класса:

Особенности использования «Swift»-методов в «Objective-C»-файлах

К сожалению, не любые (публичные) «Swift»-методы можно просто пометить @objc и использовать внутри «Objective-C». «Swift» и «Objective-C» – разные языки с разными возможностями и разной логикой, и довольно часто при написании «Swift»-кода мы пользуемся его возможностями, которыми не обладает «Objective-C» или которые реализованы фундаментально по-разному.

Например, от значений параметров по умолчанию придется отказаться. Такой метод:

…внутри «Objective-C»-кода будет выглядеть так:

( 1 – это переданное нами значение, значение по умолчанию у аргумента отсутствует.)

Названия методов

«Objective-C» обладает своей собственной системой, по которой «Swift»-метод будет назван в среде «Objective-C». В большинстве простых случаев, она вполне удовлетворительная, но зачастую требует нашего вмешательства, чтобы стать удобочитаемой. Например, название метода в духе do(thing:) «Objective-C» превратит в doWithThing: , что, возможно, не совпадает с нашим намериением. В этом случае опять-таки приходит на помощь аннотация @objc :

Методы, выбрасывающие исключения

Если «Swift»-метод помечен throws , то «Objective-C» добавит в его сигнатуру еще один параметр – ошибку, которую может выбросить метод. Например:

Использование этого метода будет происходить в духе «Objective-C» (если можно так выразиться):

Использование «Swift»-типов в параметрах и возвращаемых значениях

Если в значениях параметров или возвращаемом значении «Swift»-функции используется не стандартный «Swift»-тип, который не переносится автоматически в среду «Objective-C», этот метод использоваться в среде «Objective-C» опять-таки не выйдет… если над ним не «поколдовать».

Если этот «Swift»-тип является наследником NSObject , то, как упоминалось выше, проблем нет. Но чаще всего оказывается, что это не так. В этом случае, нас снова выручает обертка. Например, исходный «Swift»-код:

Обертка для него:

Использование внутри «Objective-C»:

Реализация «Swift»-протоколов «Objective-C»-классами

Для примера возьмем, конечно же, протокол, в параметрах или возвратных значениях методов которого используются «Swift»-типы, которые не могут быть использованы в «Objective-C:

Придется снова оборачивать. Для начала – SwiftClass :

Далее напишем свой протокол, аналогичный SwiftProtocol , но использующий обернутые версии классов:

Далее – самое интересное: объявим „Swift“-класс, адаптирующий нужный нам „Swift“-протокол. Он будет чем-то вроде моста между нашим протоколом, который мы написали для адаптации в „Objective-C“-проекте и „Swift“-методом, который принимает объект исходного „Swift“-протокола. В членах класса будет числиться экземпляр протокола, который мы описали. А методы класса в методах протокола будут вызывать методы написанного нами протокола:

К сожалению, без оборачивания метода, принимающего экземпляр протокола, не обойтись:

Не самая простая цепочка? Да. Хотя, если используемые классы и протоколы обладают ощутимым количеством методов, обертка уже не покажется такой непропорционально-объемной по отношению к исходному коду.

Собственно, использование протокола в самом „Objective-C“-кода будет выглядеть уже вполне гармонично. Реализация методов протокола:

И использование метода:

Перечисляемые типы в „Swift“ и „Objective-C“

При использовании перечисляемых типов „Swift“ в „Objective-C“-проектах есть только один нюанс: они должны иметь целочисленный Raw Type. Только после этого мы сможем аннотировать enum как @objc .

Что делать, если мы не можем изменить тип enum , но хотим использовать его внутри „Objective-C“? Мы можем, как обычно, обернуть метод, использующий экземпляры этого перечисляемого типа, и подсунуть ему наш собственный enum . Например:

Заключение

У данного подхода, конечно, есть и свои минусы. Помимо самого очевидного (написание ощутимого количества дополнительного кода), есть еще один немаловажный: „Swift“-код переносится в среду выполнения „Objective-C“ и будет работать, скорее всего, уже не так быстро или, по-крайней мере, иначе. Хотя разница во многих случаях невооруженным взглядом заметна не будет.

Следуя инструкциям, я создал заголовок моста и добавил в свой проект. К сожалению, произошла следующая ошибка:

: 0: ошибка: не удалось импортировать заголовок Objective-C '--- путь - к --- заголовку / . h'

Скриншот 1

В настройках сборки я добавил строку пути поиска заголовка к месту расположения заголовка моста, но ничего не помогло.

Кто-нибудь сталкивался с этой проблемой?

Вы могли бы лучше, чем добавлять файл заголовка самостоятельно. Используйте New File . чтобы добавить новый пустой файл Objective-c .m. Это заставит xcode предложить вам файл заголовка-моста, в который вы можете добавить свой импорт. Затем вы можете удалить только что добавленный файл .m Это новый проект или тот же, который вы делали вручную? Это новый проект, я добавил обертку поддержки Keychain, которую я однажды написал на OBJC Сожалею. Не уверен, что вы имеете в виду под добавленной оболочкой поддержки Keychain. Но я заметил, что вы работаете на iOS, вы получаете то же самое с проектом OSX, который я использовал,

Будьте осторожны, чтобы добавить файл в папку, в которой возникает ошибка! Я совершил ту же ошибку, если вы создадите файл из Xcode, он попадет в папку: Project-> Project-> Header.h

И Xcode ищет Project-> Header.h

Это означает, что вам нужно поместить файл в папку вашего проекта (ProjectName-> ProjectNameFolder)!

Надеюсь, это поможет ;)

ОБНОВЛЕНО: Я не уверен, что понял, что вы имеете в виду, но попробуйте следующее, чтобы решить вашу проблему:
1. Удалите все ваши файлы моста, которые вы создали до сих пор.
2. Выберите основную папку проекта и нажмите новый файл-> iOS-> Заголовочный файл.
3. Запишите свой импорт в созданный файл заголовка.
4. Выберите проект внутри Xcode-> Build Settings, введите в поле поиска: bridging и введите в ключ SWIFT_OBJC_BRIDGING_HEADER имя вашего файла заголовка или путь к нему!

Если вы выполните эти шаги, ваш заголовочный файл будет создан в правильном месте!

: D Надеюсь, что это поможет!

Ну, я только что попробовал этот метод, заголовок действительно виден, но, к сожалению, классы моста Obj-C все еще невидимы (после включения их в заголовок моста) Сначала ответ гласит: «Нужно поместить файл на тот же уровень xcodeproj», в конце он говорит: «Убедитесь, что файл . не на том же уровне xcodeproj». Зачем? Я имел в виду, что файл должен находиться внутри подпапки проекта, а не на том же уровне, что и xcodeproj. Пример: в папке вашего проекта у вас есть project.xcodeproj и projecttests. Файл должен находиться в папке проекта :) Я все перепробовал, но у меня ничего не работает. Это очень раздражает. Я работаю с xcode 8 и swift 3. Вы можете мне помочь? Я смущен тем, что вы говорите: «Это означает, что вам нужно разместить файл на том же уровне, что и xcodeproj!» но после того, как вы сказали: «Убедитесь, что файл находится внутри основной папки проекта не на том же уровне xcodeproj!» Который из них?

В моем случае это была ошибка из-за циклической ссылки. У меня был класс, импортированный в заголовке моста, и файл заголовка этого класса импортировал swift header ( <MODULE_NAME>-Swift.h ). Я делал это потому, что в заголовочном файле Obj-C мне нужно было использовать класс, объявленный в Swift, решение заключалось в простом использовании @class декларативного.

Таким образом, в основном ошибка говорила «Не удалось импортировать заголовок моста», ошибка выше говорила, что <MODULE_NAME>-Swift.h файл не найден, выше это была ошибка, указывающая на конкретный файл заголовка Obj-C (а именно, контроллер представления).

Как использовать совместно Objective-C и swift из одного App Target

Если мы пишем обычное приложение и хотим сделать импорт Objective-C для работы в swift необходимо создать Objective-C bridging header (связующий заголовок). Как только вы пытаетесь добавить Objective-C файл, XCode сам предложит это сделать.

bridge header

Чтобы проверить работ создадим тестовый Objective-C класс ObjcTestClass.
Создадим файл заголовка ObjcTestClass.h и поместим туда код

И файл с исходным кодом ObjcTestClass.m

В SwiftTest-Bridging-Header.h же вносим строку импорта данного класса

После этого мы можем из swift делать вызов стандартным

path - bridge header

Swift Compiler - Code Generation

Причем лучше все опции проставить до того как начнете добавлять swift файлы.

По умолчанию генерируемый заголовок содержит все swift public declarations (объявления). Если присутствует Bridging-Header то и internal declarations. Private declarations присутствуют только если они помечены с помощью @IBAction, @IBOutlet или @objc.

Для проверки я создал класс SwiftTestClass

Содержимое ObjcTestClass.h

SwiftTestClass * swiftTestClass = [ [ SwiftTestClass alloc ] init ] ;

Проверить можно в тестовых целях напрямую из ViewController

Как использовать совместно Objective-C и swift из одного Framework Target

При написании фреймворка так же бывает необходимость смешивать swift и Objective-C

Чтобы использовать Objective-C в swift необходимо
1) Defines Module выставить в YES
2) В umbrella header file (он создается автоматом для framework типа проекта) добавляем все нужные swift классы

Использование внешних библиотек
В swift командой

В Objective-C командой

При использовании swift из Objective-C мы не можем пользоваться специфическими фишками языка swift

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

Objective-C класс вполне может реализовать swift протокол

+ ( intsancetype ) recordWithRPN : ( NSUInteger ) RPM NS_SWIFT_NAME ( init ( RPM : ) ) ;

или наоборот распознается как таковой, но им не является.

+ ( id ) recordWithQuality : ( double ) quality NS_SWIFT_NAME ( record ( quality : ) ) ;

Так же этот макрос помогает избежать обрезания значений перечисления

Naming Your Product Module (именование модуля продукта)

Подводные камни

Читайте также: