Заголовок 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 будет включать в себя только те классы, которые приписаны в сгенерированном заголовке. Смотрите также эту документацию.

Класс должен быть объявлен как открытый класс @objc

Более удобным способом было бы наследовать от 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;-)

Другие вопросы по тегам