Заголовок Swift для 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>
?
Как я могу получить мои быстрые классы в этом заголовочном файле, поэтому я не получу ошибку "необъявленный идентификатор"?
Ответы
Ответ 1
Вот как я получил работу. Вы можете увидеть более крупный ответ здесь.
Измените это:
class HelloWorld {
func hello() {
println("hello world")
}
}
To:
@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];
Ответ 2
tl; dr Убедитесь, что у вас есть мостовой заголовок, если вы выполняете перекрестный вызов любой между Objective-C и Swift.
У меня была такая же проблема: я видел файл -Swift.h в DerivedData, но не упоминал о моих классах Swift. Я правильно импортировал файл заголовка, параметр "Определить модуль" был "ДА", а имя модуля продукта было правильным. Я попытался удалить и повторно добавить файлы Swift, очистить buiild, выйти из XCode и т.д., Не повезло.
Тогда я понял, что у меня не было файла -Bridging-Header.h в моем проекте, по-видимому, из-за того, как я вытащил его из предыдущего проекта. Не должно быть проблем, потому что я еще не звонил Objective-C из Swift. Но когда я добавил заголовок моста и ссылался на его путь в настройках сборки (Swift Compiler - Code Generation → Objective-C Bridging Header), это волшебным образом устранило проблему - в моем файле -Swift.h был внезапно заполнен SWIFT_CLASS ( ) доброта!
Итак, я предполагаю, что заголовок моста является фундаментальным для процесса, даже если вы НЕ используете Objective-C из Swift.
ОБНОВЛЕНИЕ: Я, наконец, понимаю это. Он связан с модификаторами public/internal access. Не уверен, что я пропустил это изначально, или если это дополнение к документам Apple, но теперь он четко заявляет: -
По умолчанию сгенерированный заголовок содержит интерфейсы для Swift объявления, отмеченные общедоступным модификатором. Он также содержит те помечены внутренним модификатором, если ваша целевая программа приложения имеет Objective-C заголовок заголовка.
Ответ 3
Собственно использовать #import "TestAppModule-Swift.h"
в ваших .m файлах. Если вам нужно ссылаться на класс в .h, используйте декларацию @class
forward.
Кроме того, если вы хотите использовать класс Swift из Objective-C, класс Swift должен быть помечен атрибутом @objc
. Xcode будет включать только классы с атрибутами, сгенерированными в сгенерированном заголовке. См. Также эту документацию.
Ответ 4
Класс должен быть объявлен как @objc общедоступный класс
Ответ 5
Более удобным способом было бы унаследовать NSObject. Например:
class HelloWorld: NSObject {
func hello() {
println("hello world")
}
}
Ответ 6
В моем случае класс не скомпилировался, потому что я сначала добавил его только к моей тестовой цели... После добавления его в мою главную цель (Build Phases → Compile Sources), он был скомпилирован и добавлен в файл заголовка.
Так много для TDD; -)
Ответ 7
В моем случае, следуя рекомендациям Apple, это не сработало, пока я не запустил проект. Редактор xcode продолжал отмечать неизвестный класс swift, пока я не щелкнул "run". Сборка прошла успешно, и быстрый метод работал.