Заголовок Swift to Objective-C не содержит классов Swift
Я пытаюсь использовать классы Swift в своем коде Objective-C, однако мои классы Swift, похоже, не появляются в сгенерированном заголовке. В результате моя сборка завершается с ошибкой "Использование необъявленного идентификатора" HelloWorld "".
Я использовал шаблоны для создания проекта под названием TestApp.
У меня есть следующие настройки сборки в моей цели:
- Название продукта: TestApp
- Название модуля продукта: TestAppModule
- Определяет модуль: да
Документация Apple говорит, чтобы использовать #import <TestApp/TestAppModule-Swift.h>
но это не работает
Вместо этого я использую #import "TestAppModule-Swift.h"
в моем ".m" файле. Кажется, это найти.
Я могу перейти к нему, и это выглядит так...
// Generated by Swift version 1.0 (swift-600.0.34.4.5)
#if defined(__has_include) && __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif
...etc...
но классы там не определены.
У меня есть файл Swift в проекте, который выглядит следующим образом...
class HelloWorld {
func hello() {
println("hello world")
}
}
Почему это не работает с использованием стандартного расположения файла заголовка #import <TestApp/TestAppModule-Swift.h>
?
Как я могу получить свои быстрые классы в этом заголовочном файле, чтобы я не получил ошибку "необъявленный идентификатор"?
7 ответов
Вот как я заставил это работать. Вы можете увидеть более масштабный ответ здесь.
Изменить это:
class HelloWorld {
func hello() {
println("hello world")
}
}
Для того, чтобы:
@objc class HelloWorld {
class func newInstance() -> HelloWorld {
return HelloWorld()
}
func hello() {
println("hello world")
}
}
Затем в вашем файле ObjC:
#import "TestApp-Swift.h"
И звоните так:
HelloWorld * helloWorld = [HelloWorld newInstance];
[helloWorld hello];
tl;dr Убедитесь, что у вас есть промежуточный заголовок, если вы делаете какие - либо перекрестные вызовы между Objective-C и Swift.
У меня была точно такая же проблема: я мог видеть файл -Swift.h в DerivedData, но он не упоминал мои классы Swift. Я правильно импортировал заголовочный файл, для параметра "Определить модуль" было задано значение "ДА", а имя модуля продукта было правильным. Я безуспешно пытался удалить и повторно добавить файлы Swift, очистить Buiild, выйти из XCode и т. Д.
Затем я понял, что в моем проекте нет файла -Bridging-Header.h, вероятно, из-за того, как я собрал его вместе из предыдущего проекта. Не должно быть проблемой, потому что я (пока) не звонил в Objective-C из Swift. Но когда я добавил заголовок моста и сослался на его путь в настройках сборки (компилятор Swift - генерация кода -> заголовок моста Objective-C), он волшебным образом решил проблему - мой файл -Swift.h внезапно заполнился SWIFT_CLASS(боже мой!
Таким образом, я предполагаю, что соединительный заголовок является основополагающим для процесса, даже если вы НЕ используете Objective-C от Swift.
ОБНОВЛЕНИЕ: я наконец понимаю это. Это связано с модификаторами публичного / внутреннего доступа. Не уверен, что я пропустил это изначально или это дополнение к документации Apple, но теперь ясно сказано:
По умолчанию сгенерированный заголовок содержит интерфейсы для объявлений Swift, помеченных модификатором public. Он также содержит помеченные внутренним модификатором, если у цели вашего приложения есть заголовок моста Objective-C.
Это правильно использовать #import "TestAppModule-Swift.h"
в ваших.m файлах. Если вам нужно сослаться на класс в.h, используйте @class
предварительная декларация.
Кроме того, если вы хотите использовать класс Swift из Objective-C, класс Swift должен быть помечен @objc
приписывать. Xcode будет включать в себя только те классы, которые приписаны в сгенерированном заголовке. Смотрите также эту документацию.
Более удобным способом было бы наследовать от NSObject. Вот так:
class HelloWorld: NSObject {
func hello() {
println("hello world")
}
}
В моем случае, следуя рекомендациям Apple, он не работал, пока я не запустил проект. Редактор xcode помечал неизвестный класс swift, пока я не нажал "запустить". Сборка прошла успешно, и быстрый метод сработал.
Возможно, вы определили класс Swift с тем же именем, что и существующий класс Objective-C, что не будет необычным, если вы захотите реорганизовать свой код Objective-C в Swift.
Пока у вас есть класс, определенный одновременно в Swift и Objective-C, компилятор полностью прекращает обновление заголовка моста ("ProductModuleName-Swift.h"
) - что также влияет на последующие изменения в других файлах Swift, соединенных мостом.
Общие сведения об импорте Swift в Objective-C см.:Импорт Swift в Objective-C | Документация для разработчиков Apple
В моем случае класс не компилировался, потому что я сначала добавил его только в свою цель тестирования... После добавления его в основную цель (этапы сборки -> источники компиляции) он был фактически скомпилирован и добавлен в файл заголовка.
Так много для TDD;-)