Я безуспешно пытаюсь работать над смешанным проектом Swift и ObjectiveC.
Мой проект состоит из 6 целей:
- Приложение
- Основной
- CoreTest
- Резюме
- Расширение WatchKit
- Приложение WatchKit
Мне удалось добавить класс Swift, который имеет одно целевое членство (приложение) и использует код ObjectiveC, передаваемый из App-Bridging-Header.h. Парадигма
«ObjectiveC в коде Swift» работает как шарм.
Вместо этого я борюсь с парадигмой «Swift в код ObjectiveC». В конкретном случае мне нужно использовать новый класс Swift внутри файла ObjectiveC.m, который является членом четырех целей.
Что я делал до сих пор, так это:
Я следил за руководством Apple по смешиванию и сопоставлению и многими потоками SO, включая этот, который, по-видимому, решает ту же проблему, но не работает.
Также видел это и это, но не сработало.
Попытались также удалить производные данные, а также очистить весь проект несколько раз, но безуспешно.
РЕДАКТИРОВАТЬ 1: Подробнее
Это объявление моего импорта класса Swift RealmSwift
@objc class MyClass: Object {}
Это фрагмент использования класса Swift внутри ObjectiveC.
MyClass *app = [[MyClass alloc] init];
Если я избегаю использования #import...-Swift.h, сборка не работает, говоря, что я использую необъявленный идентификатор «MyClass», и это правильно.
Если я использую файлы #import...-Swift.h, он говорит, что модуль X не может найти модуль Y и так далее.
РЕДАКТИРОВАТЬ 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 создал заголовок моста
- Вставлен #import «ProjectName_App-Swift.h» в файл ObjectiveC, используемый только приложением.
- Использовал класс Swift внутри этого файла
- Он компилируется! И я могу использовать класс Swift
Когда класс Swift определен для нескольких целей, а файл ObjectiveC используется этими несколькими целями, он не работает. Ошибки сборки такие: Target X -> Файл ProjectName_TargetY-Swift.h не найден. Похоже, цель не может видеть другие цели - файлы Swift.h.
Что я делаю не так? Спасибо за вашу помощь
Решение проблемы
Предположение, которое я сделал в Редактировании 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 вы импортируете скрытый заголовок моста, может иметь значение. Обычным признаком проблемы является то, что вы получаете ошибку компиляции «Неизвестное имя типа», где неизвестный тип является классом, объявленным в Objective-C. Решение состоит в том, чтобы #импортировать файл.h, содержащий объявление неизвестного типа, в ваши файлы Objective-C, прежде чем вы #импортируете скрытый заголовок моста. Это может раздражать, особенно если рассматриваемому файлу Objective-C не нужно знать об этом классе, но это решает проблему и позволяет продолжить компиляцию.
В самом конце код компилируется и запускается на устройстве и симуляторе!
Комментариев нет:
Отправить комментарий