Файл ModuleName-Swift.h не найден в xcode8

Я пытаюсь работать с смешанным проектом Swift и ObjectiveC без везения.

Мой проект состоит из 6 целей:

  • приложения
  • Core
  • CoreTest
  • Резюме
  • Расширение WatchKit
  • Приложение WatchKit

Мне удалось добавить класс Swift, в котором есть одно целевое членство (приложение), и использует код ObjectiveC, передаваемый из App-Bridging-Header.h Парадигма "ObjectiveC in Swift code" работает как шарм.

Вместо этого я борюсь с парадигмой "Swift into ObjectiveC". В конкретном случае мне нужно использовать новый класс Swift внутри файла ObjectiveC.m, который является членом четырех целей.

То, что я делал до сих пор, следующее:

  • Добавить новый файл Swift в проект Core, определяющий четыре членства (App, Core, Summary, WatchKit Ext)
  • XCode просит создать -Bridging-Header.h для трех проектов: Core, Summary и WatchKit Ext (App-Bridging-Header.h уже существует, поскольку он использовался ранее), и я соглашаюсь ( не знаю, почему он создает эти файлы внутри той же групповой папки, где я добавляю свой класс Swift, но не думаю)
  • Я создаю класс Swift, добавляя ключ @objc до класса
  • Я иду, проверяем, установлено ли Objective-C Имя заголовка сгенерированного интерфейса для всех модулей, и да, это
  • Я хочу проверить, установлен ли Определяет модуль Нет во всех модулях и установлен в Да в основном проекте, и да, это
  • Я записываю импорт для файлов -Swift.h для всех четырех целей
  • В моем классе Objective-C я пытаюсь использовать мой новый класс Swift, видимо, он работает (даже автозаполнение)
  • Я пытаюсь создать проект, но он не говорит о том, что файл -Swift.h не найден.

Я следил за Mix and Match guide от Apple и многими SO-потоками, включая этот, по-видимому, по-видимому, для решения той же самой проблемы, но она не работает.

Также видели этот и этот, но не работали.

Попробовали также удалить Derived Data, а также очистить весь проект несколько раз без везения.

РЕДАКТИРОВАТЬ 1: Подробнее

Это объявление моего класса Swift   import RealmSwift

@objc class MyClass: Object {}

Это фрагмент использования класса Swift внутри ObjectiveC

MyClass *app = [[MyClass alloc] init];

Если я избегу использовать #import...- Swift.h, сборка не позволяет сказать, что я использую Undeclared idenfier "MyClass", и это звучит.

Если я использую файлы #import...- Swift.h, он говорит, что модуль X не может найти модуль Y и т.д.

EDIT 2: имя модуля Swift

Изучая свойство SWIFT_OBJC_INTERFACE_HEADER_NAME для каждой цели, я видел, что он построен с использованием этого синтаксиса $(SWIFT_MODULE_NAME) -Swift.h мне нужно изменить SWIFT_MODULE_NAME - MODULE_NAME?

РЕДАКТИРОВАТЬ 3: Импорт

Это набор импорта для заголовков Swift в файле .m ObjectiveC. Я использую имена модулей, указанные в относительных свойствах свойств сборки. Обратите внимание, что у человека есть символ "_", так как у цели WatchKit Extension есть пробел в целевом имени.

#import "ProjectName_App-Swift.h"
#import "ProjectName_Core-Swift.h"
#import "ProjectName_Summary-Swift.h"
#import "ProjectName_WatchKit_Extension-Swift.h"

РЕДАКТИРОВАТЬ 4: Перекрестная видимость файлов -Swift.h

Я пробовал следующее:

  • Добавлен класс Swift только в целевом приложении
  • XCode создал заголовок Bridging Header
  • Вставить #import "ProjectName_App-Swift.h" в файл ObjectiveC, используемый только приложением
  • Использование класса Swift внутри этого файла
  • Он компилируется! И я могу использовать класс Swift

Когда класс Swift определен для нескольких целей, а файл ObjectiveC используется этими несколькими целями, он не работает. Ошибки сборки выглядят следующим образом: Файл Target X → "ProjectName_TargetY-Swift.h" не найден. Кажется, что цель не может видеть другие цели -Swift.h.

Что я делаю неправильно? Спасибо за вашу помощь.

Ответы

Ответ 1

Предположение, сделанное в Edit 4, оказалось правильным. Если проект имеет несколько целей, файлы "-Swift.h" не могут быть импортированы все в один файл .m ObjectiveC.

Итак, есть одно решение, которое необходимо принять, и изменить параметр сборки SWIFT_OBJC_INTERFACE_HEADER_NAME и сделать его одинаковым для разных целей. Для этого измените инструкцию, которая генерирует это свойство из $(SWIFT_MODULE_NAME) -Swift.h в $(PROJECT_NAME) -Swift.h, как описано здесь

Также можно установить параметр "Имя модуля продукта" в "Параметры сборки" одинаковым для всех модулей (я установил его в $(PROJECT_NAME)), так что создаваемый файл -Swift.h имеет то же имя по всем модулям. Это устраняет необходимость добавления/проверки макросов препроцессора.

После выполнения этой "Чистой сборки" нажмите Alt и перейдите в меню "Продукт". Поскольку имя заголовка распределяется между целевыми объектами, теперь его можно импортировать один раз в файле .m ObjectiveC, и все цели могут быть полезны для классов Swift.

Если после сборки все еще отображается ошибка, убедитесь, что заголовок можно получить из XCode, нажав Cmd на его имя. Он должен открыть файл, содержащий код, похожий на этот:

SWIFT_CLASS("_TtC27ProjectName_Summary11MyClass")
@interface MyClass : NSObject
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

Если необходимо убедиться, что эти заголовки создаются, откройте терминал и используйте эту команду

find ~/Library/Developer/Xcode/DerivedData -name "*Swift.h"

Вы должны увидеть один заголовок для каждой цели

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

Именно там, где в верхней части файла .m вы #import, заголовок скрытого моста может иметь значение. Обычным признаком проблемы является то, что вы получаете ошибку компиляции "Неизвестное имя типа", где неизвестный тип - это класс, объявленный в Objective-C. Решение состоит в том, чтобы #import.h файл, содержащий объявление для неизвестного типа, в ваших файлах Objective-C, прежде чем вы #import заголовок скрытого моста. Сделать это может раздражать, особенно если этот файл Objective-C не нуждается в знании об этом классе, но он решает проблему и позволяет компиляцию продолжить.

В самом конце код компилируется и запускается на устройстве и симуляторе!

Ответ 2

У меня была аналогичная проблема, и я почти закончил тратить целый день на выяснение проблемы, следуя советам других разработчиков StackOverflow и нескольких других источников.

Я обновлялся с XCode 7.3.1 до XCode 8.2.1 и Swift 2.2 до Swift 3.0.1.
В моем случае я понял, что файл PROJECT_NAME-Swift.h не создан:

~/Library/Developer/Xcode/DerivedData/PRODUCT-NAME-hdkrxixrxbiorwesffpqvefxsrzl/Build/Intermediates/PRODUCT-NAME.build/Debug/PRODUCT-NAME.build/Objects-normal/x86_64/PRODUCT-NAME-Swift.h.

Я предполагаю, что он каким-то образом пытается ссылаться на этот файл заголовка по указанному выше пути и, следовательно, на ошибку. Я вручную скопировал его. После этого не делал чистой сборки. Это разрешило мою проблему, и быстрый файл заголовка начал создаваться для дальнейшей компиляции и сборки.

Ответ 3

В моем случае он отлично работает в Xcode 8, но файлы с

#import "Project-Swift.h"

отсутствует импорт, как описано LucioB

Использование Xcode 9 удаляет эти ошибки