不能在Objective-C中使用Swift类

我尝试在我的应用程序中集成Swift代码。我的应用程序是用Objective-C编写的,我添加了一个Swift类。我已经完成了在这里所描述的所有内容。但我的问题是Xcode没有创建-Swift.h文件,只有桥接头。我创建了它,但它实际上是空的。 我可以在Swift中使用我所有的ObjC类,但我不能反之亦然。我用@objc标记了我的swift类,但它没有帮助。我现在该怎么办?< / p >

编辑: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
}
}
172005 次浏览

不要自己创建头文件。删除您所创建的。

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

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

确保您的项目定义了一个模块,并为该模块指定了名称。然后重建,Xcode会创建-Swift.h头文件,你就可以导入了。

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

我有同样的问题,原来模块名称中的特殊符号被xcode取代(在我的情况下,破折号最终成为下划线)。在项目设置中检查“模块名称”以查找项目的模块名称。之后使用ModuleName-Swift.h或在设置中重命名模块。

我花了大约4个小时在我的基于Xcode Objective-C的项目中启用Swift。我的myproject-Swift.h文件已成功创建,但我的Xcode没有看到我的Swift-classes。所以,我决定创建一个新的Xcode object -based项目,最后,我找到了正确的答案!希望这篇文章能帮助到一些人:-)

Step by Step Swift integration for Xcode object -based project:

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

    import Foundation
    
    
    // use @objc or @objcMembers annotation if necessary
    class Foo {
    //..
    }
    
  4. Open Build Settings and check these parameters:

    • Defines Module : YES

      Copy & Paste parameter name in a search bar

    • Product Module Name : myproject

      Make sure that your Product Module Name doesn't contain any special characters

    • Install Objective-C Compatibility Header : YES

      Once you've added *.swift file to the project this property will appear in Build Settings

    • Objective-C Generated Interface Header : myproject-Swift.h

      This header is auto-generated by Xcode

    • Objective-C Bridging Header : $(SRCROOT)/myproject-Bridging-Header.h
  5. Import Swift interface header in your *.m file.

    #import "myproject-Swift.h"
    

    不要注意错误和警告。

    李< /引用> < / >
  6. 清理并重建Xcode项目。
  7. 利润!

文件是自动创建的(这里讨论的是Xcode 6.3.2)。但您不会看到它,因为它在派生数据文件夹中。在用@objc标记swift类后,编译,然后在派生数据文件夹中搜索Swift.h。您应该在那里找到Swift头文件。

我有问题,Xcode重命名我的my-Project-Swift.hmy_Project-Swift.h Xcode不喜欢 "." "-"等符号。使用上述方法,你可以找到文件名并将其导入到Objective-C类中

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

我刚刚发现,在项目中添加swift文件目录是行不通的。您需要首先为该目录创建一个组,然后添加swift文件…

< p >包括 #导入myProject-Swift.h文件到。m或。h文件中

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

我的问题是-swift.h文件的自动生成不能理解CustomDebugStringConvertible的子类。我把class改为NSObject的子类。在此之后,-swift.h文件现在正确地包含了类。

对于那些有框架的目标的人可能也有帮助:

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

#import <ProductName/ProductModuleName-Swift.h>

而不是

#import "ProductModuleName-Swift.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)至关重要。我只把它放在第二部分(目标字段),项目字段应该是空的:enter image description here否则,它没有为我生成正确的“Project- swift .h”文件(它不包括swift方法)。

允许Xcode做它的工作,不要手动添加/创建Swift头。只需要在你的Swift类ex之前添加@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 !

我也有同样的问题,最后似乎它们没有连接到相同的目标。 ObjC类附加到Target1和Target2, Swift类只附加到Target1,在ObjC类内部不可见

希望这能帮助到一些人。

在我的例子中,除了这些步骤:

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

为了创建productName-Swift.h文件,我需要将类设置为公共:

import UIKit


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

我的问题是我在xcode创建桥文件后卡住了,但我仍然在头文件MYPROJECTNAME-swift.h中得到了错误

1.我检查终端和搜索所有自动创建的swift桥文件:

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

你看xcode创建了什么。

  1. 在我的例子中,我在我的项目名称中有空格,xcode将其替换为_

细节: Objective-C项目与Swift 3代码在Xcode 8.1

任务:

  1. 在objective-c类中使用swift enum
  2. 在swift类中使用objective-c enum

完整的样品

1. Objective-C类使用Swift枚举

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代码。这个文件自动生成(我没有在项目中创建这个头文件的物理副本),你只能设置这个文件的名称:

enter image description here

enter image description here

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

2. Swift类使用Objective-C枚举

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会建议你创建桥接头。

enter image description here

你可以在这里更改桥接头文件的名称:

enter image description here

Bridging-Header.h

#import "ObjcClass.h"

使用

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

结果

enter image description here


更多的样品

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

3.从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!!!";

结果

enter image description here

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!!!";
}

结果

enter image description here

5. 在Objective-c代码中使用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()

有两个条件,

  • 在objective - c文件中使用swift文件。
  • 使用你的objective c文件在swift文件。

因此,为了达到这个目的,你必须遵循以下步骤:

  • 在objective-c项目中添加swift文件,反之亦然。
  • 创建头文件(.h)。
  • 进入建立设置并执行以下搜索步骤,

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

之后,清理并重新构建项目。

在objective - c文件中使用swift文件。

在这种情况下,首先在swift文件中你的类之前写“@objc”。

之后,在objective - c文件中,写这个,

  #import "YourProjectName-Swift.h"

使用你的objective c文件在swift文件。

在你的头文件中,写这个,

  #import "YourObjective-c_FileName.h"

我希望这对你有所帮助。

我遇到的问题是,我会在objective-c桥接头中添加类,而在那些被导入的objective-c头中,它们试图导入swift头。它不喜欢那样。

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

我不需要改变构建中的任何设置,也不需要将@obj添加到类中。

我所要做的就是创建bridge-header,当我在Objective-c项目中创建Swift类时,它会自动创建。然后我要做的就是

导入“Bedtime-Swift.h"-在objective-c文件中,需要使用swift文件。

好吧,在阅读了所有的评论,并尝试了一遍又一遍,我设法将swift类包含到我的Big obj-c项目中。 所以,谢谢你的帮助。 我想分享一个技巧,帮助我更好地理解这个过程。 在.m类中,转到swift目标名称的导入行#import "myTargetName-Swift.h" 点击键:

命令+鼠标点击->跳转到定义 enter image description here < / p > 在那里你可以看到从swift到obj-c的所有转换,在那里你会发现在obj-c中重新声明的各种函数。

希望这个技巧能像帮助我一样帮助你

在做了以上所有事情之后,我仍然得到了错误。我的问题是我需要的Swift文件由于某种原因没有添加到bundle资源中。

我通过去[MyTarget] > Build Phases > Copy Bundle Resources修复了这个问题,然后单击加号按钮并添加Swift文件。

对于Swift 5:

  1. @objc关键字添加到类和方法中
  2. 在类和方法中添加public关键字
  3. 让你的类继承NSObject
  4. 建设项目
  5. 在Objective-C文件中放入#import "MyProject-Swift.h"

    @objc
    public class MyClass: NSObject {
    
    
    @objc
    public func myMethod() {
    
    
    }
    }
    

当你添加新的Swift文件到项目,请确保你添加它们到正确的目标。 请确保你要使用的每个swift文件都继承了NSObject类,并带有@ObjCMembers注释 在ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES选项下的构建设置中更改为YES。 在构建设置中,在选项DEFINES_MODULE.

下更改为YES

在Objective-C中使用Swift类

如果你要在App Target中导入代码(将Objective-C和Swift混合在一个项目中),你应该使用下一个导入行#import "<#YourProjectName#>-Swift.h"将Swift代码暴露给Objective-C代码[在项目中混合Swift和Objective-C代码]

在这篇文章中,我将描述如何将Swift静态库导入Objective-C代码

Objective-C consumer -> Swift静态库

Xcode 10.2.1版

创建Swift静态库

Create Swift static library之后添加以下内容:

公开Swift API。使用Objective-C<一口>[对]< /一口>中的Swift函数

在构建之后,你应该找到一个<product_name>-Swift.h文件,该文件应该位于DerivedSources [文件未找到] . [/sup> .

Objective-C消费者与Swift静态库

Drag and drop将二进制转换成Xcode项目__abc1

Link Library<一口>[未定义的符号]< /一口> [链接vs嵌入] . [/sup> .

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[库未找到] . <一口>(递归路径)< /一口>

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[模块未找到] . [/sup> . (递归路径)

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项目中。当Xcode询问时,按下Create Bridging Header(它将创建module_name-Bridging-Header.h)并设置该文件的路径

Project editor -> select a target -> Build Settings -> Swift Compiler - General -> Objective-C Bridging Header

导入模块到Objective-C客户端代码__abc0 <一口> [module_name] < /一口>

#import "module_name-Swift.h"

更多的例子在这里

XCode 11.3.1:

当我想在objc代码中使用Swift内部类时,它不会编译错误“未定义的符号”(对于麻烦的内部类和外部类),我检查了生成的“-swift.h”头,两个类都在那里。

在尝试了几个小时后,我将内部类转换为正常类并编译

我清理项目,删除DerivedData文件夹,然后进行编译。

我使用CocoaPods和我的库中的Swift类无法从示例应用程序中的Objective-C代码中定位,因为它的项目和目标与库命名相同,所以我必须删除Objective-C Generated Interface Name值,以便它们与库中的值不冲突。