首页 文章

不能在Objective-C中使用Swift类

提问于
浏览
226

我尝试在我的app中集成 Swift 代码 . 我的应用程序是用 Objective-C 编写的,我添加了一个 Swift 类 . 我做了所有描述的here . 但我的问题是 Xcode 没有创建 -Swift.h 文件,只有桥接头 . 所以我创建了它,但它反过来了 . 反之亦然 . 我用 @objc 标记了我的快速课程,但它没有帮助 . 我现在能做什么?

编辑:Apple说:“当您将Swift代码导入Objective-C时,您依靠 Xcode-generated 头文件将这些文件公开给Objective-C . [...]此 Headers 的名称是您的产品模块名称,然后添加“-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
    }
}

21 回答

  • 4

    我有同样的问题,结果发现模块名称中的特殊符号被xcode取代(在我的情况下,破折号最后是下划线) . 在项目设置中,选中"module name"以查找项目的模块名称 . 之后使用 ModuleName-Swift.h 或在设置中重命名模块 .

  • 8

    Details: Objective-C项目,在Xcode 8.1中使用Swift 3代码

    Tasks:

    • 在objective-c类中使用swift枚举

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

    enter image description here

    如果编译器找不到您的头文件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会建议你创建桥接头 .

    enter image description here

    You can change bridging header file name 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!!!";
    

    Result

    enter image description here

    4.调用Objective-c类来自SWIFT代码

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

    Result

    enter image description here

    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()
    
  • 26

    该文件是自动创建的(这里谈论Xcode 6.3.2) . 但是你在Derived Data文件夹中赢了't see it, since it' . 使用 @objc 标记swift类后,编译,然后在Derived Data文件夹中搜索 Swift.h . 你应该在那里找到Swift Headers .

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

  • 2

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

    P.S你不会在文件检查器中找到“myProject-Swift.h”,它是隐藏的 . 但它是由app自动生成的 .

  • 32

    @sig答案是最好的之一,然而,它对我来说不适用于旧项目(不是新的!),我需要一些修改 . 经过很多变化后,我找到了我的食谱(使用XCode 7.2):

    • 产品模块名称:$(PRODUCT_NAME:c99extidentifier)

    • 定义模块:否

    • 嵌入式内容包含Swift:NO

    • 安装Objective-C兼容性 Headers :是

    • Objective-C Bridging Header:ProjectName-Bridging-Header.h

    最后一点(5)至关重要 . 我只把它放在第二部分(Targets字段),Project字段应该留空:
    enter image description here
    否则,它没有为我生成正确的"Project-Swift.h"文件(它不包括swift方法) .

  • 60

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

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

    • 创建新的 *.swift 文件(在Xcode中)或使用Finder添加它

    • 当Xcode询问你时,创建一个 Objective-C bridging header

    • 实现你的Swift类:

    import Foundation
    
    // use @objc or @objcMembers annotation if necessary
    class Foo {
        //..
    }
    
    • 打开构建设置并检查这些参数:

    • Defines Module : YES

    在搜索栏中复制并粘贴参数名称

    • Product Module Name : myproject

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

    • Install Objective-C Compatibility Header : YES

    将* .swift文件添加到项目后,此属性将显示在“构建设置”中

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

    此标头由Xcode自动生成

    • Objective-C Bridging Header : $(SRCROOT)/myproject-Bridging-Header.h

    • 在* .m文件中导入Swift接口标头

    #import "myproject-Swift.h"
    

    不要注意错误和警告 .

    • 清理并重建您的Xcode项目

    • 利润!

  • 0

    不要自己创建头文件 . 删除您创建的那个 .

    确保您的Swift类标记为 @objc 或继承自 NSObject (直接或间接)派生的类 .

    如果您的项目中有任何编译器错误,Xcode将不会生成该文件 - 确保您的项目构建完整 .

  • 11

    允许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!

  • 3

    对于那些拥有 Framework target 的人来说也许有帮助:

    自动生成的头文件的 import statement 从应用目标看起来是 a bit different . 除了在其他答案中提到的其他事项使用

    #import <ProductName/ProductModuleName-Swift.h>
    

    代替

    #import "ProductModuleName-Swift.h"
    

    根据Mix & Match上的Apples文档,用于框架目标 .

  • 474

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

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

  • 0

    There is two condition,

    • 在目标c文件中使用swift文件 .

    • 在swift文件中使用目标c文件 .

    So, For that purpose, you have to follow this steps:

    • 在Objective-c项目中添加swift文件,反之亦然 .

    • 创建 Headers (.h)文件 .

    • 转到 Build Settings 并执行以下搜索步骤,

    • 搜索此文本"brid"并设置头文件的路径 .

    • "Defines Module":是的 .

    • "Always Embed Swift Standard Libraries":是的 .

    • "Install Objective-C Compatibility Header":是的 .

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

    在目标c文件中使用swift文件 .

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

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

    #import "YourProjectName-Swift.h"
    

    在swift文件中使用目标c文件 .

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

    #import "YourObjective-c_FileName.h"
    

    我希望这能帮到您 .

  • 10

    在我的情况下,除了这些步骤:

    • 产品模块名称:myproject

    • 定义模块:是

    • 嵌入式内容包含Swift:是

    • 安装Objective-C兼容性 Headers :是

    • Objective-C桥接 Headers :$(SRCROOT)/Sources/SwiftBridging.h

    我需要将类设置为 public 才能创建 productName-Swift.h 文件:

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

    我刚刚发现将swift文件目录添加到项目中是行不通的 . 您需要先为目录创建一个组,然后添加swift文件......

  • 0

    我遇到了同样的问题,最后看起来他们没有附加到同一个目标 . ObjC类附加到Target1和Target2,Swift类仅附加到Target1,并且在ObjC类中不可见 .

    希望这有助于某人 .

  • 4

    我有同样的错误:找不到 myProjectModule-Swift.h 文件", but, in my case, real reason was in wrong deployment target: " Swift 在OS X早于10.9时不可用;请将 MACOSX_DEPLOYMENT_TARGET 设置为10.9或更高版本(目前为'10.7')“因此,当我将部署目标更改为10.9时 - 项目已成功编译 .

  • 9

    我的问题是-swift.h文件的自动生成无法理解CustomDebugStringConvertible的子类 . 我改为将类更改为NSObject的子类 . 之后,-swift.h文件现在正确地包含了该类 .

  • 0

    我的问题是我在xcode创建桥文件后卡住但仍然在头文件名MYPROJECTNAME-swift.h中出错

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

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

    你看到xcode创建了什么 .

    在我的情况下

    • ,我的项目名称中有空格而xcode替换为'_'
  • 2

    我遇到的问题是我会在我的objective-c桥接头中添加类,并且在导入的那些objective-c头文件中,他们试图导入swift头 . 它不喜欢那样 .

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

  • -1

    我没有必要更改构建中的任何设置或将@obj添加到类中 .

    我所要做的就是创建bridge-header,这是在我将Swift类创建到Objective-c项目时自动创建的 . 然后我就必须这样做

    导入“Bedtime-Swift.h”< - 需要使用该swift文件的objective-c文件内部 .

  • 0

    好吧,在阅读了所有评论并尝试阅读并再次尝试之后,我设法将swift类包含在我的Big obj-c项目中 . 所以,感谢所有的帮助 . 我想分享一个提示,帮助我更好地理解这个过程 . 在.m类中,转到swift目标名称#import“myTargetName-Swift.h”的导入行,然后单击键:

    命令鼠标单击 - >跳转到定义
    enter image description here

    在那里你可以看到从swift到obj-c的所有翻译,你会发现在obj-c中重新声明了各种函数 . 希望这个提示能帮助你,就像它帮助我一样 .

  • 14

    完成上述所有操作后,我仍然遇到错误 . 我的问题最终是我所需的Swift文件由于某种原因没有添加到捆绑资源 .

    我通过转到[MyTarget]> Build Phases> Copy Bundle Resources来修复此问题,然后单击加号按钮并添加了Swift文件 .

相关问题