Нельзя использовать классы Swift внутри Objective-C
Я пытаюсь интегрировать код Swift
в мое приложение. Мое приложение написано в Objective-C
, и я добавил класс Swift
. Я сделал все, что описано здесь. Но моя проблема заключается в том, что Xcode
не создал файл -Swift.h
, а только мосты. Поэтому я создал его, но он фактически пуст.
Я могу использовать все классы ObjC в Swift, но я не могу это сделать наоборот. Я отметил мой быстрый класс @objc
, но это не помогло. Что я могу сделать сейчас?
EDIT: Apple говорит: "Когда вы импортируете код Swift в Objective-C, вы полагаетесь на заголовочный файл Xcode-generated
, чтобы выставить эти файлы в Objective-C. [...] Название этого заголовка - ваш продукт имя модуля, а затем добавление" -Swift.h".
Теперь, когда я хочу импортировать этот файл, он дает ошибку:
//MainMenu.m
#import "myProjectModule-Swift.h" //Error: 'myProjectModule-Swift.h' file not found
@implementation MainMenu
Вот мой файл FBManager.swift:
@objc class FBManager: NSObject {
var descr = "FBManager class"
init() {
super.init()
}
func desc(){
println(descr)
}
func getSharedGameState() -> GameState{
return GameState.sharedGameState() //OK! GameState is written in Objective-C and no error here
}
}
Ответы
Ответ 1
Я потратил около 4 часов, пытаясь включить Swift
в моем проекте Xcode
Objective-C. Мой файл myproject-Swift.h
был успешно создан, но мой Xcode
не увидел мой Swift-classes
. Итак, я решил создать новый Xcode
Objc-проект и, наконец, я нашел правильный ответ! Надеюсь, этот пост кому-нибудь поможет :-)
Пошаговая интеграция Swift для проекта на базе Xcode Objc:
- Создайте новый файл
*.swift
(в Xcode) или добавьте его с помощью Finder.
- Создайте
Objective-C bridging header
, когда Xcode спросит вас об этом.
Реализуйте свой класс Swift:
import Foundation
// use @objc or @objcMembers annotation if necessary
class Foo {
//..
}
Откройте настройки сборки и проверьте следующие параметры:
- Определяет модуль:
YES
Копировать и Вставить имя параметра в строку поиска
- Название модуля продукта:
myproject
Убедитесь, что имя вашего модуля продукта не содержит специальных символов
- Установите заголовок совместимости Objective-C:
YES
После добавления файла *.swift
в проект это свойство появится в настройках сборки
- Заголовок интерфейса, сгенерированный Objective-C:
myproject-Swift.h
Этот заголовок автоматически генерируется Xcode
- Заголовок моста Objective-C:
$(SRCROOT)/myproject-Bridging-Header.h
Импортируйте заголовок интерфейса Swift в ваш файл *.m.
#import "myproject-Swift.h"
Не обращайте внимания на ошибки и предупреждения.
- Очистите и перестройте проект Xcode.
- Прибыль!
Ответ 2
Не создавайте файл заголовка самостоятельно. Удалите созданную вами.
Убедитесь, что ваши классы Swift отмечены @objc
или наследуются от класса, который выводит (прямо или косвенно) из NSObject
.
Xcode не будет генерировать файл, если у вас есть какие-либо ошибки компилятора в вашем проекте - убедитесь, что ваш проект строит чисто.
Ответ 3
Разрешить Xcode выполнять свою работу, не добавлять/создавать Swift-заголовок вручную. Просто добавьте @objc перед вашим классом Swift ex.
@objc class YourSwiftClassName: UIViewController
В вашем проекте выберите поиск ниже флагов и измените его на YES (Оба проекта и цели)
Defines Module : YES
Always Embed Swift Standard Libraries : YES
Install Objective-C Compatibility Header : YES
Затем очистите проект и создайте его один раз, после того, как сборка завершится успешно (возможно, она должна) импортировать ниже заголовочного файла в ваш .m файл objective-c.
#import "YourProjectName-Swift.h"
Boooom!
Ответ 4
Также полезно для тех из вас, у кого есть Рамка-цель:
Оператор импорта автоматически сгенерированного файла заголовка выглядит как немного отличающийся от целей приложения. В дополнение к другим вещам, упомянутым в других ответах, используйте
#import <ProductName/ProductModuleName-Swift.h>
вместо
#import "ProductModuleName-Swift.h"
согласно документации на яблоки Mix и Match для целей инфраструктуры.
Ответ 5
Убедитесь, что ваш проект определяет модуль, и вы дали имя модулю. Затем перестройте, и Xcode создаст заголовочный файл -Swift.h
, и вы сможете импортировать его.
Вы можете установить определение модуля и имя модуля в настройках проекта.
Ответ 6
Детали: Objective-C проект с кодом Swift 3 в Xcode 8.1
Задачи:
- Использовать swift перечисление в классе Objective-C
- Использовать перечисление Objective-C в классе swift
ПОЛНЫЙ ОБРАЗЕЦ
1. Objective-C класс, который использует Swift enum
ObjcClass.h
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, ObjcEnum) {
ObjcEnumValue1,
ObjcEnumValue2,
ObjcEnumValue3
};
@interface ObjcClass : NSObject
+ (void) PrintEnumValues;
@end
ObjcClass.m
#import "ObjcClass.h"
#import "SwiftCode.h"
@implementation ObjcClass
+ (void) PrintEnumValues {
[self PrintEnumValue:SwiftEnumValue1];
[self PrintEnumValue:SwiftEnumValue2];
[self PrintEnumValue:SwiftEnumValue3];
}
+ (void) PrintEnumValue:(SwiftEnum) value {
switch (value) {
case SwiftEnumValue1:
NSLog(@"-- SwiftEnum: SwiftEnumValue1");
break;
case SwiftEnumValue2:
case SwiftEnumValue3:
NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
break;
}
}
@end
Обнаружить код Swift в коде Objective-C
В моем примере я использую SwiftCode.h для обнаружения кода Swift в Objective-C. Этот файл генерируется автоматически (я не создал физическую копию этого заголовочного файла в проекте), и вы можете установить только имя этого файла:
![введите описание изображения здесь]()
![введите описание изображения здесь]()
Если компилятор не может найти файл заголовка Swift, попытайтесь скомпилировать проект.
2. Класс Swift, который использует Objective-C enum
import Foundation
@objc
enum SwiftEnum: Int {
case Value1, Value2, Value3
}
@objc
class SwiftClass: NSObject {
class func PrintEnumValues() {
PrintEnumValue(.Value1)
PrintEnumValue(.Value2)
PrintEnumValue(.Value3)
}
class func PrintEnumValue(value: ObjcEnum) {
switch value {
case .Value1, .Value2:
NSLog("-- ObjcEnum: int value = \(value.rawValue)")
case .Value3:
NSLog("-- ObjcEnum: Value3")
break
}
}
}
Определить код Objective-C в коде Swift
Вам нужно создать файл заголовка моста. Когда вы добавляете файл Swift в проект Objective-C или файл Objective-C в быстрый проект Xcode предложит вам создать заголовок моста.
![введите описание изображения здесь]()
Здесь вы можете изменить имя файла заголовка:
![введите описание изображения здесь]()
Соединяя-header.h
#import "ObjcClass.h"
Использование
#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];
Результат
![введите здесь описание изображения]()
БОЛЬШЕ ОБРАЗЦОВ
Полные шаги интеграции Objective-C и Swift, описанные выше. Теперь я напишу несколько других примеров кода.
3. Вызов класса Swift из Objective-C кода
Класс Swift
import Foundation
@objc
class SwiftClass:NSObject {
private var _stringValue: String
var stringValue: String {
get {
print("SwiftClass get stringValue")
return _stringValue
}
set {
print("SwiftClass set stringValue = \(newValue)")
_stringValue = newValue
}
}
init (stringValue: String) {
print("SwiftClass init(String)")
_stringValue = stringValue
}
func printValue() {
print("SwiftClass printValue()")
print("stringValue = \(_stringValue)")
}
}
Objective-C код (код вызова)
SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";
Результат
![введите описание изображения здесь]()
4. Вызвать Objective-C класс из кода Swift
Objective-C class (ObjcClass.h)
#import <Foundation/Foundation.h>
@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end
ObjcClass.m
#import "ObjcClass.h"
@interface ObjcClass()
@property NSString* strValue;
@end
@implementation ObjcClass
- (instancetype) initWithStringValue:(NSString*)stringValue {
NSLog(@"ObjcClass initWithStringValue");
_strValue = stringValue;
return self;
}
- (void) printValue {
NSLog(@"ObjcClass printValue");
NSLog(@"stringValue = %@", _strValue);
}
- (NSString*) stringValue {
NSLog(@"ObjcClass get stringValue");
return _strValue;
}
- (void) setStringValue:(NSString*)newValue {
NSLog(@"ObjcClass set stringValue = %@", newValue);
_strValue = newValue;
}
@end
Быстрый код (код вызова)
if let obj = ObjcClass(stringValue: "Hello World!") {
obj.printValue()
let str = obj.stringValue;
obj.stringValue = "HeLLo wOrLd!!!";
}
Результат
![введите описание изображения здесь]()
5. Используйте расширение Swift в Objective-C code
Быстрое расширение
extension UIView {
static func swiftExtensionFunc() {
NSLog("UIView swiftExtensionFunc")
}
}
Objective-C код (код вызова)
[UIView swiftExtensionFunc];
6. Используйте расширение Objective-C в быстром коде
Objective-C extension (UIViewExtension.h)
#import <UIKit/UIKit.h>
@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end
UIViewExtension.m
@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
NSLog(@"UIView objcExtensionFunc");
}
@end
Быстрый код (код вызова)
UIView.objcExtensionFunc()
Ответ 7
У меня была такая же проблема, и оказалось, что специальные символы в имени модуля заменяются на xcode (в моем случае тире оказались символом подчеркивания). В настройках проекта проверьте "имя модуля", чтобы найти имя модуля для вашего проекта. После этого либо используйте ModuleName-Swift.h
, либо переименуйте модуль в настройках.
Ответ 8
Файл создается автоматически (здесь речь идет о Xcode 6.3.2). Но вы не увидите этого, так как он находится в папке Derived Data. После маркировки вашего быстрого класса @objc
, скомпилируйте, затем найдите Swift.h
в папке Derived Data. Здесь вы должны найти заголовок Swift.
У меня была проблема, что Xcode переименовал мой my-Project-Swift.h
в my_Project-Swift.h
Xcode не нравится
"." "-"
и т.д. символы. С помощью приведенного выше метода вы можете найти имя файла и импортировать его в класс Objective-C.
Ответ 9
Просто включите #import "myProject-Swift.h" в .m или .h файле
P.S Вы не найдете "myProject-Swift.h" в инспекторе файлов скрытым. Но он создается приложением автоматически.
Ответ 10
Существует два условия:
- Используйте ваш быстрый файл в объектном файле c.
- Используйте свой объектный файл c в быстром файле.
Итак, для этой цели вам необходимо выполнить следующие действия:
После этого очистите и перестройте свой проект.
Используйте ваш быстрый файл в объектном файле c.
В этом случае сначала напишите "@objc" перед вашим классом в swift файле.
После этого в своем объектном файле c напишите это,
#import "YourProjectName-Swift.h"
Используйте свой объектный файл c в быстром файле.
В этом случае, в вашем файле заголовка, напишите это,
#import "YourObjective-c_FileName.h"
Надеюсь, это поможет вам.
Ответ 11
@sig ответ один из лучших, однако он не работал у меня со старым проектом (не новым!), мне нужны были некоторые изменения. После многих вариаций я нашел рецепт для меня (используя XCode 7.2):
- Имя модуля продукта: $(PRODUCT_NAME: c99extidentifier)
- Определяет модуль: NO
- Встроенный контент содержит Swift: NO
- Установить Objective-C Заголовок совместимости: YES
- Objective-C Заголовок моста: ProjectName-Bridging-Header.h
Последняя точка (5) имела решающее значение. Я помещаю его только во второй раздел (поле "Цели" ), поле "Проект" должно быть пустым:
В противном случае он не создавал для меня файл "Project-Swift.h" (он не включал быстрые методы).
Ответ 12
В моем случае, помимо этих шагов:
- Имя модуля продукта: myproject
- Определяет модуль: ДА
- Встроенный контент содержит Swift: YES
- Установить Objective-C Заголовок совместимости: YES
- Objective-C Заголовок моста: $(SRCROOT)/Sources/SwiftBridging.h
Мне нужно было поставить класс как public, чтобы создать файл productName-Swift.h:
import UIKit
@objc public class TestSwift: NSObject {
func sayHello() {
print("Hi there!")
}
}
Ответ 13
Я только что обнаружил, что добавление каталога быстрых файлов в проект не будет работать. Сначала вам нужно создать группу для каталога, а затем добавить быстрые файлы...
Ответ 14
У меня была такая же проблема, и, наконец, оказалось, что они не привязаны к тем же целям.
Класс ObjC привязан к Target1 и Target2, класс Swift привязан только к Target1 и не отображается внутри класса ObjC.
Надеюсь, это поможет кому-то.
Ответ 15
Моя проблема в том, что я застрял после того, как xcode создал файл моста, но все же я получил ошибку в имени файла заголовка MYPROJECTNAME-swift.h
1.I проверить терминал и искать все автоматически созданные файлы быстрого моста:
find ~/library/Developer/Xcode/DerivedData/ -name "*-Swift.h"|xargs basename|sort -
вы видите, какой xcode создан.
- В моем случае у меня было место в имени моего проекта, а вместо xcode это "_"
Ответ 16
Для Swift 5:
- Добавьте ключевое слово
@objc
в ваш класс и методы - Добавьте
public
ключевое слово в ваш класс и методы - Пусть ваш класс наследуется от
NSObject
- Построить проект
-
Поместите #import "MyProject-Swift.h"
в ваш файл Objective-C
@objc
public class MyClass: NSObject {
@objc
public func myMethod() {
}
}
Ответ 17
Использование классов Swift в Objective-C
Если вы собираетесь импортировать код внутри цели приложения (смешивая Objective-C и Swift в одном проекте), вам следует использовать следующую строку импорта #import "<#YourProjectName#>-Swift.h"
, чтобы представить Swift-код в код Objective-C [Mixing Swift and Objective-C code in a project]
В этом посте я опишу, как импортировать статическую библиотеку Swift в код Objective-C
Потребитель Objective-C → Swift статическая библиотека
Версия Xcode 10.2.1
Создать статическую библиотеку Swift
Создать проект библиотеки или создать целевой объект библиотеки
File -> New -> Project... -> Cocoa Touch Static Library
//or
Project editor -> Add a Target -> Cocoa Touch Static Library
Добавить файлы .swift
Select '.swift' file -> Select File Inspectors Tab -> Target Membership -> Select the target
//or
Project editor -> select a target -> Build Phases -> Compile Sources -> add files
Разоблачить Swift API. Использовать функции Swift из Objective-C[About]
Сборка библиотеки - ⌘ Command + B или Product -> Build
Примечание. Убедитесь, что вы создали библиотеку для той же архитектуры процессов, что и код клиента.
Найти сгенерированный вывод[Build location]
Products group -> lib<product_name>.a -> Show in Finder
Каталог включает в себя
lib<product_name>.a
- встроенная статическая библиотека
- Папка
<product_name>.swiftmodule
, которая включает в себя:
.swiftdoc
- документы
.swiftmodule
- общедоступный интерфейс/определения
![]()
Также вы должны найти файл <product_name>-Swift.h
, который должен находиться в DerivedSources
[File not found]
Использование статической библиотеки Swift
Drag and drop
двоичный файл в проект Xcode[About]
Link Library
[Undefined symbols] [Link vs Embed]
Project editor -> select a target -> General -> Linked Frameworks and Libraries -> add -> Add Others... -> point to 'lib<product_name>.a' file
//or
Project editor -> select a target -> Build Phases -> Link Binary With Libraries -> add -> Add Others... -> point to 'lib<product_name>.a' file
Добавить Library Search paths
[Library not found for] [Recursive path]
Project editor -> select a target -> Build Settings -> Search Paths -> Library Search paths -> add path to the parent of 'lib<product_name>.a' file
Добавить Header Search Paths
[Module not found] [Recursive path]
Project editor -> select a target -> Build Settings -> Search Paths -> Header Search Paths -> add path to generated '<product_name>-Swift.h' file
Добавить пустой .swift file
в проект Objective-C.[Undefined symbols] When Xcode ask press Create [TG420](it will create [TG421]) and setup a path to this file in
[TG16]
Import module to the Objective-C client code[File not found] [module_name]
[TG17]
More examples here
Ответ 18
У меня такая же ошибка: myProjectModule-Swift.h
file not found ", но в моем случае реальная причина была в неправильной цели развертывания:" Swift
недоступно в OS X раньше, чем 10.9, установите MACOSX_DEPLOYMENT_TARGET
в 10.9 или новее (в настоящее время это "10.7" )
поэтому, когда я изменил цель развертывания на 10.9 - проект был скомпилирован успешно.
Ответ 19
Моя проблема заключалась в том, что автогенерация файла -swift.h не способна понять подкласс CustomDebugStringConvertible. Вместо этого я заменил класс на подкласс NSObject. После этого файл -swift.h теперь включил класс правильно.
Ответ 20
У меня были проблемы с тем, что я бы добавил классы в мой заголовок моста objective-c, а в этих objective-c заголовках, которые были импортированы, они пытались импортировать быстрый заголовок. Это не понравилось.
Итак, во всех моих классах objective-c, которые используют swift, но также мосты, ключ должен был убедиться, что вы используете объявления прямого класса в заголовках, а затем импортируете файл "* -Swift.h" в. m файл.
Ответ 21
Мне не нужно было менять какие-либо настройки в сборке или добавлять @obj в класс.
Все, что мне нужно было сделать, это создать bridge-header, который автоматически создавался при создании классов Swift в проекте Objective-c. И тогда я просто должен был сделать
import "Bedtime-Swift.h" <- внутри файла target-c, необходимого для использования этого файла swift.
Ответ 22
Ну, после прочтения всех комментариев, попыток, чтения и повторных попыток мне удалось включить быстрые классы в мой проект Big obj-c. Итак, спасибо за помощь. Я хотел поделиться одним советом, который помог мне лучше понять процесс. В классе .m, перейдите к строке импорта с именем целевого объекта swift #import "myTargetName-Swift.h" и нажмите клавишу:
команда + щелчок мыши → Перейти к определению ![enter image description here]()
Там вы можете увидеть все переводы от swift к obj-c, и вы найдете различные функции, повторно объявленные в obj-c. Надеюсь, этот совет поможет вам так же, как и мне.
Ответ 23
Когда вы добавляете новые файлы Swift в проект, пожалуйста, убедитесь, что вы добавляете их в правильные цели.
Пожалуйста, убедитесь, что каждый файл swift, который вы собираетесь использовать, наследует класс NSObject и помечается как @ObjCMembers.
Измените на YES в настройках сборки под опцией ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES.
Измените на YES в настройках сборки под опцией DEFINES_MODULE.
Ответ 24
После всего вышеперечисленного я все еще получил ошибки. В итоге моя проблема заключалась в том, что нужные мне файлы Swift не были добавлены в ресурсы пакета.
Я исправил это, выбрав [MyTarget]> "Фазы сборки"> "Копировать ресурсы комплекта", затем нажал кнопку "плюс" и добавил файлы Swift.