Objective-C中不能使用Swift类

我尝试将Swift代码集成到我的应用程序中。我的应用程序是用Objective-C编写的,我添加了一个Swift类。 我已经做了一切描述在这里 。 但我的问题是, Xcode还没有创建-Swift.h文件,只有-Swift.h 。 所以我创建了它,但实际上是空的。 我可以在Swift中使用所有的ObjC类,但是我不能这样做。 我用@objc标记了我的swift类,但是没有帮助。 我现在能做什么?

编辑:苹果说:“当你将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 } } 

我花了大约4个小时,试图在基于Xcode Objective-C的项目中启用Swift 。 我的“ myproject-Swift.h ”文件已经成功创建,但我的Xcode没有看到我的Swift-classes 。 所以,我决定创建一个新的基于Xcode Objc项目,最后我找到了正确的答案! 希望这个职位将有助于某人:-)

一步一步Swift集成Xcode基于Objc的项目:

  1. 创建新的*.swift文件(在Xcode中)或使用Finder添加它
  2. 当Xcode询问你时,创建一个Objective-C bridging header
  3. @objc属性实现你的Swift类:

     import UIKit @objc public class CustomView: UIView { override func draw(_ rect: CGRect) { // Drawing code } } 
  4. 打开构建设置并检查这些参数:

    • 定义模块: YES
    • 产品模块名称: myproject

      确保您的产品模块名称不包含任何特殊字符

    • 安装Objective-C兼容性头文件: YES

      一旦将*.swift文件添加到项目中,此属性将出现在“生成设置”中

    • Objective-C生成的接口头文件: myproject-Swift.h

      这个头文件是由Xcode自动生成的

    • Objective-C桥接头: $(SRCROOT)/myproject-Bridging-Header.h
  5. 在* .m文件中导入Swift接口标题

     #import "myproject-Swift.h" 

    不要注意错误和警告。

  6. 清理并重建您的Xcode项目
  7. 利润!

不要自己创建头文件。 删除你创建的一个。

确保你的Swift类用@objc标记,或者从NSObject派生(直接或间接)的类继承。

如果您的项目中有任何编译器错误,Xcode将不会生成该文件 – 确保您的项目干净地构建。

允许Xcode执行它的工作,不要手动添加/创建Swift头。 只要在你的Swift类前添加@objc。

 @objc class YourSwiftClassName: UIViewController 

在你的项目设置中搜索下面的标志,并将其更改为YES(项目和目标)

 Defines Module : YES Always Embed Swift Standard Libraries : YES Install Objective-C Compatibility Header : YES 

然后清理项目并构建一次,构建成功后(可能应该)导入到您的objective-c类.m文件中的头文件下面

 #import "YourProjectName-Swift.h" 

Boooom!

也可能有助于你的框架目标的人

自动生成的头文件的导入语句与应用程序目标有点不同 。 除了在其他答案中提到的其他事情使用

 #import <ProductName/ProductModuleName-Swift.h> 

代替

 #import "ProductModuleName-Swift.h" 

根据苹果关于混合与匹配框架目标的文档。

确保你的项目定义了一个模块,并给出了模块的名称。 然后重建,Xcode将创建-Swift.h头文件,您将能够导入。

您可以在项目设置中设置模块定义和模块名称。

我有同样的问题,事实证明,模块名称中的特殊符号被替换为Xcode(在我的情况下,破折号最后是下划线)。 在项目设置中,选中“模块名称”以查找项目的模块名称。 之后,使用ModuleName-Swift.h或在设置中重命名模块。

该文件是自动创建的(在这里谈论Xcode 6.3.2)。 但是你不会看到它,因为它在Derived Data文件夹中。 使用@objc标记swift类@objc ,编译,然后在Derived Data文件夹中搜索Swift.h 。 你应该在那里找到Swift标题。

我有这个问题,Xcode更名为my my-Project-Swift.h my_Project-Swift.h Xcode不喜欢"." "-" "." "-"等符号。 使用上面的方法,您可以找到文件名并将其导入到Objective-C类。

只需在.m或.h文件中包含#import“myProject-Swift.h”

PS你将不会在文件检查器中找到“myProject-Swift.h”它是隐藏的。 但它是由应用程序自动生成的。

详细信息:在Xcode 8.1中使用Swift 3代码的Objective-C项目

任务:

  1. 在Objective-C类中使用快速枚举
  2. 在swift类中使用objective-c enum

完整的示例

1.使用Swift枚举的Objective-C类

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 

检测Objective-C代码中的Swift代码

在我的示例中,我使用SwiftCode.h来检测Objective-C中的Swift代码。 这个文件自动生成(我没有在一个项目中创建这个头文件的物理副本),你只能设置这个文件的名字:

在这里输入图像描述

在这里输入图像描述

如果编译器找不到你的头文件Swift代码,试着编译这个项目。

2.使用Objective-C枚举的Swift类

 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 } } } 

检测Swift代码中的Objective-C代码

您需要创建桥接头文件。 当您在Objective-C项目中添加Swift文件或者在Swift项目中添加Objective-C文件时,Xcode会建议您创建桥接标头。

在这里输入图像描述

您可以在此更改桥接头文件名称:

在这里输入图像描述

转职Header.h

 #import "ObjcClass.h" 

用法

 #import "SwiftCode.h" ... [ObjcClass PrintEnumValues]; [SwiftClass PrintEnumValues]; [SwiftClass PrintEnumValue:ObjcEnumValue3]; 

结果

在这里输入图像描述


更多样本

上面描述的完整集成步骤Objective-c和Swift 。 现在我将写一些其他的代码示例。

3.从Objective-c代码中调用Swift类

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.从Swift代码中调用Objective-c类

Objective-C类(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 

Swift代码(调用代码)

 if let obj = ObjcClass(stringValue: "Hello World!") { obj.printValue() let str = obj.stringValue; obj.stringValue = "HeLLo wOrLd!!!"; } 

结果

在这里输入图像描述

5.在Objective-c代码中使用Swift扩展

Swift扩展

 extension UIView { static func swiftExtensionFunc() { NSLog("UIView swiftExtensionFunc") } } 

Objective-C代码(调用代码)

 [UIView swiftExtensionFunc]; 

6.在Swift代码中使用Objective-C扩展

Objective-C扩展(UIViewExtension.h)

 #import <UIKit/UIKit.h> @interface UIView (ObjcAdditions) + (void)objcExtensionFunc; @end 

UIViewExtension.m

 @implementation UIView (ObjcAdditions) + (void)objcExtensionFunc { NSLog(@"UIView objcExtensionFunc"); } @end 

Swift代码(调用代码)

 UIView.objcExtensionFunc() 

有两个条件,

  • 在目标c文件中使用你的swift文件。
  • 在swift文件中使用你的目标c文件。

所以,为了这个目的,你必须按照下面的步骤进行:

  • 在一个Objective-C项目中添加你的swift文件,反之亦然。
  • 创建标题(.h)文件。
  • 转到构建设置并执行以下搜索步骤,

    1. 搜索这个文本“brid”并设置头文件的路径。
    2. “定义模块”:是。
    3. “总是嵌入Swift标准库”:是的。
    4. “安装Objective-C兼容性头”:是。

之后,清理并重建您的项目。

在目标c文件中使用你的swift文件。

在这种情况下,首先在swift文件中写上“@objc”。

之后,在你的目标c文件中,写下这个,

  #import "YourProjectName-Swift.h" 

在swift文件中使用你的目标c文件。

在这种情况下,在你的头文件中,写这个,

  #import "YourObjective-c_FileName.h" 

我希望这会帮助你。

@sig答案是最好的之一,但是,它不适合我的旧项目(不是新的!),我需要一些修改。 经过很多变化,我找到了我的食谱(使用XCode 7.2):

  1. 产品模块名称:$(PRODUCT_NAME:c99extidentifier)
  2. 定义模块:NO
  3. 嵌入式内容包含Swift:NO
  4. 安装Objective-C兼容性头文件:YES
  5. Objective-C桥接头:ProjectName-Bridging-Header.h

最后一点(5)是至关重要的。 我只把它放在第二部分(目标字段),项目字段应该留空: 在这里输入图像描述 否则,它不会为我生成正确的“Project-Swift.h”文件(它不包含swift方法)。

就我而言,除了这些步骤:

  1. 产品模块名称:myproject
  2. 定义模块:是
  3. 嵌入式内容包含Swift:YES
  4. 安装Objective-C兼容性头文件:YES
  5. Objective-C桥接头:$(SRCROOT)/Sources/SwiftBridging.h

我需要把这个类作为public来创建productName-Swift.h文件:

 import UIKit @objc public class TestSwift: NSObject { func sayHello() { print("Hi there!") } } 

我刚刚发现,添加一个swift文件目录到一个项目将无法正常工作。 您需要先为该目录创建一个组,然后添加swift文件…

我也遇到了同样的问题,最后看来他们并没有遵守同样的目标。 ObjC类附加到Target1和Target2,Swift类只附加到Target1,在ObjC类中不可见。

希望这有助于某人。

我有同样的错误: myProjectModule-Swift.h文件“,但在我的情况下,真正的原因是错误的部署目标:” Swift在10.9以前的OS X上不可用; 请将MACOSX_DEPLOYMENT_TARGET设置为10.9或更高版本(当前为“ MACOSX_DEPLOYMENT_TARGET ”),因此,当我将部署目标更改为10.9时,项目已成功编译。

我的问题是,自动生成的-swift.h文件无法理解CustomDebugStringConvertible的子类。 我把类改为NSObject的一个子类。 在那之后,-swift.h文件现在包含了这个类。

我的问题是我被困在Xcode创建桥文件后,但仍然在头文件名称错误MYPROJECTNAME-swift.h

我检查终端并搜索所有自动创建的快速桥接文件:

find ~/library/Developer/Xcode/DerivedData/ -name "*-Swift.h"|xargs basename|sort -

你看看Xcode创建了什么。

  1. 在我的情况下,我有我的项目名称和Xcode空间替换这是'_'

我有问题,我会添加类到我的objective-c桥头,并在那些被导入的目标C头,他们试图导入swift头。 它不是那样的。

因此,在所有使用swift的Objective-C类中,也是桥接的,关键是确保在头文件中使用前向类声明,然后在.m文件中导入“* -Swift.h”文件。