Перейдите к заголовку Objective C, не созданному в Xcode 6
Недавно я работал над добавлением Swift в существующий проект, чтобы попробовать его в реальной жизни.
После добавления исходного файла Swift в проект у меня не возникает проблем с получением "Bridging Header", то есть Objective-C для Swift.
Но заголовочный файл -Swift.h, который должен предоставлять классы Swift с пометкой @objc или подклассы классов ObjC, нигде не найден:-(
Я не вижу каких-либо конкретных инструкций о том, как выполнить использование моего нового подкласса, написанного на Swift, в моем основном коде приложения (который все еще является Obj-C).
Приложение, которым я являюсь ведущим разработчиком, имеет довольно большую кодовую базу (70000 строк), поэтому о его переходе за один раз не может быть и речи.
32 ответа
Теперь это работает.
- Проект должен иметь имя модуля продукта, которое не содержит пробелов.
- Определяет модуль должен быть установлен на Да в настройках сборки, в разделе Упаковка.
Наконец работает. Спасибо всем за помощь:-)
У меня была похожая проблема, и я обнаружил, что вы можете только добавить
#import “ProductModuleName-Swift.h”
к файлам obj-c .m, а не к файлам.h для заголовка зонтика, который будет найден
Я обнаружил, что должен был исправить все ошибки сборки, прежде чем он сгенерирует файл.
Проблема для меня заключалась в том, что это была проблема курица / яйцо, поскольку я не видел никаких ошибок сборки, пока я фактически не закомментировал #import
заявление:
//#import "ProductModuleName-Swift.h"
что выявило кучу других ошибок в моем коде Swift.
После того, как я исправил эти новые ошибки и успешно собрал сборку исходного кода, я раскомментировал #import
и бинго! Заголовок был создан и импортирован правильно:)
Если вы похожи на меня, вы, вероятно, ошиблись названием заголовка. После того, как я немного ударился головой, я искал файл в DerivedData и, конечно же, он там есть. На моей установке (я полагаю, используя стандартную папку производных данных):
cd ~/Library/Developer/Xcode/DerivedData
find * -iname '*Swift.h'
Найдем это. Если ничего в этой папке не совпадает, то Xcode не генерирует его.
Я использую Xcode Version 6.2 (6C86e)
Если в имени вашего модуля проекта есть пробелы, вы должны заменить пробелы подчеркиванием.
Например, если имя вашего проекта "Мой проект", вы должны использовать:
#import "My_Project-Swift.h"
* Единственная важная вещь: *
использовать определенное "Имя модуля продукта" в цели, а затем -Swift.h
#import <Product Module Name>-Swift.h
// in each ObjectiveC .m file having to use swift classes
// no matter in which swift files these classes sit.
Независимо от того, установлено ли для параметра "Определить модуль" значение "Да" или "Нет", или если проект "Имя модуля продукта" не установлен.
Напоминание: классы Swift должны быть производными от NSObject или помечены атрибутом @objc, чтобы быть доступными для ObjectiveC / Foundation || Какао...
Я хотел добавить еще одну причину, по которой вы можете столкнуться с этой проблемой - я создавал среду, которая смешивала код Swift и Objective-C. Я не смог импортировать классы Swift вне фреймворка - я проверил файл -Swift.h, и он генерировался, но был пустым.
Проблема оказалась очень, очень простой - я не объявил ни один из моих классов Swift публичным! Как только я добавил ключевое слово public в классы, я смог использовать их из классов внутри и вне фреймворка.
Также следует отметить, что внутри фреймворка (внутри файлов.m только в качестве другого ответа упоминается) мне пришлось импортировать файл -Swift.h как:
#import <FrameworkName/FrameworkName-Swift.h>
У меня такая же проблема. Похоже, вам нужно настроить параметры (определяет модуль и имя модуля продукта), прежде чем добавить свой первый файл Swift.
Если вы сделаете это впоследствии, файл "*-Swift.h" не будет создан для этого проекта, даже если вы добавите дополнительные файлы Swift или удалите файл Swift и создадите новый.
Позвольте мне поделиться своим опытом использования Swift в старом проекте objc. Я не должен был установить Defines module
в YES
,
В моем случае мне нужно было вручную убедиться, что существует заголовок объекта Bridging. В моих настройках сборки присутствовало только сгенерированное имя заголовка интерфейса.
Это привело к созданию файла MyApp-Swift.h, но без каких-либо следов моих классов Swift.
В документации Apple говорится, что вам будет предложено создать промежуточный заголовок при добавлении вашего первого файла swift. Ну, я не был. Я вручную добавил MyApp-Bridging-header.h
файл и указал на него в поле "Objective-C Bridging Header". Это сделало мой файл MyApp-Swift.h заполненным моими классами Swift.
Документы: импорт Swift в Objective-C
Вот еще один вариант файла moduleName-Swift.h, который не генерируется.
Я решил включить IOS Charts в свой проект, но не хотел смешивать источники в одном каталоге, поэтому я поместил папку Project Charts рядом с папкой проекта моего кода. Я перетащил проект Charts в панель навигатора моего проекта и включил каркас в список встроенных двоичных файлов целевого объекта моего проекта в общих настройках проекта и установил переключатель " Код встроенного содержимого содержит Swift Code" на "да" на вкладке " Параметры сборки" моего проекта в разделе "Параметры сборки ".
Файл moduleName-Swift.h моего проекта никогда не будет генерироваться, независимо от того, какие другие параметры или параметры предложены здесь. Наконец, используя метод Лу Z для поиска файлов -Swift.h, я увидел, что файл Charts-Swift.h генерируется глубоко в каталоге xcode Build моего проекта в Charts.framework/Headers/
Решением использования пакета Swift ios-charts Даниэля Джинди без включения кода в исходный каталог моего проекта было добавить:
#import "Charts/Charts-Swift.h"
Для модулей, составляющих схему данных моего проекта.
Имя файла всегда предшествует вашему имени цели. Это называется именем продукта, но практически это имя цели. Так что, если вы хотите построить новую цель, будьте готовы that_target-Swift.h
файл.
Один из способов справиться с этим
- Добавьте препроцессор для каждой вашей цели, который является именем вашей цели (без пробелов). Ex.
MY_TARGET=1
, Добавьте это в Настройки проекта-> Настройки сборки-> Макросы препроцессора для каждой из ваших целей. - Если вы используете файл PCH,
Добавьте эти строки в файл PCH
#if MY_TARGET==1
#include "My_Target-Swift.h"
#elif THAT_TARGET==1
#include "That_Target-Swift.h"
#endif
Преимущество использования файла PCH заключается в том, что вам не нужно включать заголовки везде.
- Если вы не используете файл PCH, просто добавьте эти же строки в один заголовок и включайте этот заголовок везде, где вам нужно использовать классы swift.
Это должно работать просто отлично.
Если XCode фактически генерирует ваш заголовок -Swift.h (глубоко внутри DerivedData), но он не относится к вашим классам Swift, убедитесь, что у вас также определен мостовой заголовок. То, как я читал документы, подразумевало, что мне нужно только это для вызова Objective-C из Swift, но, похоже, это необходимо и для вызова Swift из Objective-C.
Смотрите мой ответ: /questions/42569347/zagolovok-swift-to-objective-c-ne-soderzhit-klassov-swift/42569365#42569365
РЕДАКТИРОВАТЬ: Это из-за общественных и внутренних модификаторов доступа, как я в конечном итоге нашел объяснил в документации Apple:
По умолчанию сгенерированный заголовок содержит интерфейсы для объявлений Swift, помеченных модификатором public. Он также содержит помеченные внутренним модификатором, если у цели вашего приложения есть заголовок моста Objective-C.
Разобраться с тем, что есть у многих здесь, но добавить соответствующий снимок экрана. Код Swift и Obj-C, безусловно, могут жить вместе. Это не игра "все или ничего".
Чтобы получить доступ к файлам Swift в Objective-C, все, что вам нужно сделать, это добавить этот вызов в ваш файл Obj-C (в файле.m / реализация):
#import "{product_module_name}-Swift.h"
(Где {product_module_name} представляет имя модуля продукта вашего проекта). Вместо того, чтобы пытаться угадать имя модуля вашего продукта или определить угловые случаи с пробелами и специальными символами, просто перейдите на вкладку параметров сборки в проекте и введите "имя модуля продукта" - инспектор покажет вам ваше. Мое было то, чего я не ожидал. Посмотрите на этот снимок экрана, если вы запутались.
И чтобы заставить код Obj-c работать в Swift, вам просто нужно добавить файл заголовка моста и импортировать туда соответствующие заголовки Obj-C.
Хорошо, вот все, что вам действительно нужно!
1. Удалите все добавленные вами файлы swift и скомпилируйте код без ошибок.
----------
----------
2. Перейдите к настройкам сборки "Проекты" и задайте имя модуля продукта. Проект должен иметь имя модуля продукта, которое не содержит пробелов.
----------
----------
3.Defines Module должен быть установлен в Yes в настройках сборки, в разделе Packaging, в вашем проекте, а не в цель!
----------
----------
4. Теперь создайте файл swift или контроллер представления, в file-> newFile->
----------
----------
Он попросит создать bridging-header, позволить ему сделать таковой. Если вы отклонили его один раз, вам придется вручную добавить -Bridging-Header.h
5.Добавьте @objc в контроллер, чтобы сообщить компилятору, что существует некоторый файл swift, который необходимо открыть для ObjectiveC.
----------
----------
6.Скомпилируйте проект и импортируйте #import "-Swift.h" в любой из контроллеров targetC, и он будет работать! Вы можете щелкнуть по нему, чтобы увидеть актуальный файл!
----------
----------
Надеюсь это поможет!
Этот ответ касается варианта использования, когда у вас уже может быть какой-то код Objective-C, который вызывает классы Swift, и вы начинаете получать эту ошибку.
Как исправить проблему
Следующие шаги в конечном итоге решили все проблемы для меня. Я прочитал выше, кто-то упоминает "курица и яйцо", и именно эта концепция привела меня к этой процедуре. Этот явный процесс показывает, что нужно удалить любой код Objective C, ссылающийся на классы Swift, до тех пор, пока не будет сгенерирован заголовок.
- Закомментируйте оператор #import "ProductModuleName-Swift.h" в файле реализации Objective C
- Закомментируйте любые ссылки в файле реализации Objective C на классы Swift
- Очистить и построить
- Разрешить все ошибки / предупреждения
- Удалить комментарий к выражению #import "ProductModuleName-Swift.h"
- Очистите и соберите (успешно или исправьте все оставшиеся ошибки, убедитесь, что вы не ссылаетесь ни на какие классы Swift в Objective-C на данный момент. Если это так, временно закомментируйте их)
- Убедитесь, что "ProductModuleName-Swift.h" создан Cmd-Clicking для имени класса оператора #import "ProductModuleName-Swift.h".
- Удалите комментарий к коду, ссылающемуся на классы Swift, в файле реализации Objective-C.
- Очистите и постройте как обычно ("ProductModuleName-Swift.h" должен быть сгенерирован, и ваш код Objective C, ссылающийся на классы Swift, может использоваться как обычно)
Примечание: ответы об изменении пробелов на подчеркивания и определения модуля на YES, приведенные выше, по-прежнему применяются при выполнении этого процесса, как и правила, указанные в документации Apple.
Мостовой путь заголовка
При одной ошибке файл ProductModuleName-Bridging-Header.h не был найден в процессе сборки. Этот факт породил ошибку
:0: ошибка: заголовок моста '/Users/Shared/Working/abc/abc-Bridging-Header.h' не существует
Более тщательная проверка ошибки показала, что файл никогда не будет существовать в указанном месте, потому что он действительно находится в (неправильный путь)
'/Users/Shared/Working/abc/abc/abc-Bridging-Header.h. быстрый поиск настроек сборки цели / проектов, чтобы сделать исправление вручную, и файл abc-Swift.h был снова автоматически сгенерирован.
Самое главное, что этот файл невидим!!! По крайней мере, это в Xcode6 beta5. В вашей рабочей области не будет такого файла с именем "YourModule-Swift.h". Просто убедитесь, что у вас есть имя модуля и определено, что модуль имеет значение yes, и используйте его в своем классе Objective-C.
Вы должны импортировать заголовок в классах Objective C, который является:
#import “ProductModuleName-Swift.h”
Он генерируется автоматически по ссылке: "Любые файлы Swift в вашей цели будут видны в файлах Objective-C .m, содержащих эту инструкцию импорта".
Проект должен иметь имя модуля без пробелов. Определяет модуль должен быть установлен на Да в настройках сборки, в разделе Упаковка. прокомментировал утверждение #import:
Если все еще у вас возникла ошибка при импорте "ProductModuleName-Swift.h", тогда
//#import "ProductModuleName-Swift.h"
что выявило кучу других ошибок в моем коде Swift.
Как только я исправил эти новые ошибки и успешно собрал сборку исходного кода, я раскомментировал #import и bingo! Заголовок был создан и импортирован правильно:)
Просто хедз-ап для тех, кто использовал "." там имя проекта. Xcode заменит "." с подчеркиванием "_" для Swift-версии файла заголовка моста. Как ни странно, генерируемый Bridging-Header.h не заменяет точки подчеркиванием.
Например, проект с именем My.Project будет иметь следующие имена файлов заголовка моста.
Bridging-Header.h (сгенерированный автоматически)
My.Project-Bridging-header.h
Swift.h
My_Project.h
Я надеюсь, что это поможет любому, кто использовал период и застрял, как я. Этот файл можно найти в следующем месте.
Macintosh HD / Пользователи /пользователь/Library/Developer/Xcode/DerivedData/My.Project-fntdulwpbhbbzdbyrkhanemcrfil/Build/Intermediates/My.Project.build/Debug-iphonesimulator/My.Project.build/Derived
Береги себя,
Джон
Фактический файл в проекте не создан ([ProductModuleName]-Swift.h). Cmd + Нажмите на импорт либо генерирует его на лету (и в памяти), чтобы вы могли видеть, как выполняется связывание, либо открывает файл где-то в некоторой директории кэша Xcode, но его нет в директории проекта.
Вам нужно установить опцию "Определяет проект модуля " (в настройках сборки цели) на " Да", а если имя вашего модуля содержит пробелы или тире - использовать _ во всех импортах файла [ProductModuleName] -Swift.h.
Вы можете импортировать его во все файлы.h и.m, где вы используете быстрые типы, или вы можете импортировать его в.pch.
Поэтому, если мой Модуль (проект) называется "Тестовый проект", я импортировал бы его следующим образом, в файл.pch моего проекта (только там):
#import "Test_Project-Swift.h"
Я нашел это решение
- Создать SwiftBridge.h
- положить #import "ProductModuleName-Swift.h"
- Сделать этот.h файл общедоступным (важно) Выберите файл -> В Показать инспектор файла (правая панель) -> Сделать его общедоступным
Теперь вы можете
#import "SwiftBridge.h"
вместо ProductModuleName-Swift.h
Это обходное решение, для следующей версии Xcode, я думаю, эта проблема будет решена. Удачи
В моем случае я должен был установить цель развертывания как минимум "OS X 10.9" и -Swift.h
заголовок был автоматически сгенерирован. Имейте в виду, что при изменении целевой версии развертывания вы можете получить множество предупреждений об устаревании, особенно если у вас более старая и очень большая база кода Objective C. В нашем случае у нас также было много работы с XIB-файлами и классами просмотра.
Я нашел трюк, который всегда работает на меня.
- Создайте #import "ProductModuleName-Swift.h" в файле appDelegate.h и в файле ProductName-Prefix.pch. Если у вас его нет в xcode 6, вы можете создать его таким образом. Почему ProjectName-Prefix.pch не создается автоматически в Xcode 6?
- Ctrl + Shift+ K, чтобы очистить ваш код, если вы получили сообщение об ошибке "ProductModuleName-Swift.h", удалите его из файла appDelegate.h.
- Очистите ваш код еще раз. Теперь все будет работать как шарм
- Если вы снова получаете сообщение об ошибке "ProductModuleName-Swift.h", теперь снова создайте файл appDelegate.h и снова очистите код.
Выполняйте эту работу (удаляйте и создавайте файл "ProductModuleName-Swift.h" из файла appDelegate.h и очищайте код) каждый раз, когда вы получаете эту ошибку, чтобы заставить ее замолчать.
Я с трудом определял, как мой модуль / target-c импортирует заголовки swift. Я тоже прочитал много статей здесь.
Но окончательный ответ для вашего имени проекта со всеми включенными в него специальными символами (будь то '.' Или цифрой или пробелом) - вы можете найти текст, который будет работать для вас, в "Имя модуля продукта" в настройках сборки цели.,
Например, мое целевое имя начиналось с цифры - "1 мг", а в поле, указанном выше, в качестве имени моего модуля было указано "_mg".
поэтому я использовал #import "_mg-Swift.h", и это сработало.
Если бы вы смогли построить проект раньше, без проблем, связанных с “ProductModuleName-Swift.h” not found
ошибка, и теперь вы снова получаете эти неприятные ошибки, причина может быть в ваших последних изменениях.
Для меня это было (случайно) неправильно .swift
кодировка файла. Отмена изменений и возвращение обратно вручную, делает работу.
Это может быть очевидным моментом (может быть, слишком очевидным), но для создания заголовка у вас должен быть хотя бы один файл swift в проекте. Если вы пишете шаблон или код конфигурации с намерением написать swift позже, импорт не будет работать.
Если вы используете что-то вроде Cocoapods (и работаете не из проекта, а из рабочей области), попробуйте открыть проект и собрать его перед открытием рабочей области и сборкой. YMMV.
У меня была похожая проблема, но мой проект компилировался раньше, и внезапно произошла ошибка после изменения кода нескольких файлов. Мне потребовалось время, чтобы выяснить, почему я получаю ошибку "Файл не найден" для файла my project-swift.h. Изменения кода, которые я сделал, имели некоторые ошибки. XCode не указывал, вместо того, чтобы поставить эти ошибки все время, показывая "Файл не найден". Затем я получил копию кода предыдущей версии, и я сравнил новый код с одним файлом. После каждого слияния файла выполняется проект, чтобы найти ошибку. Итак, суть в том, что если у вас есть ошибка в вашем коде, Xcode может просто отобразить "file not found error" для файла my project-swift.h. Скорее всего, у вас есть ошибка компиляции в вашем проекте. Очистите эти ошибки, и это будет работать.
Мне пришлось удалить код Swift WatchOS2 из моего проекта Objective C. И только после этого XCode предложил сгенерировать -Swift.h
Файл генерировался, но XCode не смог его найти (я использовал ответ Лу Зелла, чтобы доказать, что он генерируется).
Это было мое исправление (XCode 9.2) для смешанной среды ObjC/Swift:
- Найдите ожидаемый сгенерированный файл в DerivedData, выполнив поиск в finder (TargetName-Swift.h)
- Перетащите его в свой проект в XCode и UNCHECK копировать файлы.
- Нажмите на файл в XCode и откройте инспектор файлов (первая вкладка на правой панели).
- Изменить местоположение с относительного на группу на относительное для сборки продуктов
Первые два шага должны позволять вам просто создавать и использовать свой проект, но последние два позволяют ему работать на других компьютерах (т.е. он все еще работает при совместной работе над командным проектом).