不能在Objective-C中使用Swift类

dnn*_*agy 251 objective-c ios swift

我尝试Swift在我的app中集成代码.我的应用程序是写入的Objective-C,我添加了一个Swift类.我做了这里描述的所有事情.但我的问题是Xcode没有创建-Swift.h文件,只有桥接头.所以我创造了它,但它实际上是空的.我可以在Swift中使用我所有的ObjC类,但我不能这样做.我标记了我的快速课程,@objc但没有帮助.我现在能做什么?

编辑: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
Run Code Online (Sandbox Code Playgroud)

这是我的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
    }
}
Run Code Online (Sandbox Code Playgroud)

sig*_*sig 507

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

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

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

    import Foundation
    
    // use @objc or @objcMembers annotation if necessary
    class Foo {
        //..
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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"
    
    Run Code Online (Sandbox Code Playgroud)

    不要注意错误和警告.

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

  • 用你那4个小时,你节省了我们的数百小时,非常感谢:)保存在我最喜欢的;) (11认同)
  • @Asaf实际上,是的,这个文件是由Xcode自动生成并位于你的项目构建路径中.因此,你可以在Finder/Console中手动找到这个文件,或者使用Cmd + LeftClick在`#import"myproject-Swift.h"中直接在Xcode中打开它. (6认同)
  • 有没有人在文档中看到提到所需的配置(至少对我而言):https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_77在上面的第4步?如果是我错过了它.谢谢@sig. (2认同)
  • 我的问题更简单 - 我找不到文件`"myproject-Swift.h"`所以在我看来它似乎不起作用.显然,该文件在项目导航器中不可见. (2认同)
  • 至于我#5足以解决问题!! (2认同)

Bil*_*ill 64

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

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

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

  • @anders陷入那个循环时,可以使用`find~/library/Developer/Xcode/DerivedData/-name"*-Swift.h"| xargs basename | sort -u`查看文件是否是用意外创建的像我这样的名字.:) (13认同)
  • 正在建设是我的关键.无法构建,因为它无法找到我的-swift.h文件,但它无法找到我的-swift.h文件,因为它无法构建:/ (8认同)

Bha*_*odi 37

允许Xcode完成其工作,不要手动添加/创建Swift标头.只需在Swift类之前添加@objc.

@objc class YourSwiftClassName: UIViewController
Run Code Online (Sandbox Code Playgroud)

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

Defines Module : YES
Always Embed Swift Standard Libraries : YES
Install Objective-C Compatibility Header : YES
Run Code Online (Sandbox Code Playgroud)

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

#import "YourProjectName-Swift.h" 
Run Code Online (Sandbox Code Playgroud)

Boooom!


Jee*_*hut 28

对于那些拥有Framework目标的人来说,这也许有帮助:

自动生成的头文件的import语句与app目标略有不同.除了在其他答案中提到的其他事项使用

#import <ProductName/ProductModuleName-Swift.h>
Run Code Online (Sandbox Code Playgroud)

代替

#import "ProductModuleName-Swift.h"
Run Code Online (Sandbox Code Playgroud)

根据关于框架目标的Mix&Match的 Apples文档.


Leo*_*ica 14

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

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


Vas*_*huk 13

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

任务:

  1. 在objective-c类中使用swift枚举
  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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

在此输入图像描述

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

在此输入图像描述

转职Header.h

#import "ObjcClass.h"
Run Code Online (Sandbox Code Playgroud)

用法

#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述


更多样品

完整集成步骤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)")
    }

}
Run Code Online (Sandbox Code Playgroud)

Objective-C代码(调用代码)

SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Swift代码(调用代码)

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

结果

在此输入图像描述

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

迅捷扩展

extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}
Run Code Online (Sandbox Code Playgroud)

Objective-C代码(调用代码)

[UIView swiftExtensionFunc];
Run Code Online (Sandbox Code Playgroud)

6.在swift代码中使用Objective-c扩展

Objective-C扩展(UIViewExtension.h)

#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end
Run Code Online (Sandbox Code Playgroud)

UIViewExtension.m

@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end
Run Code Online (Sandbox Code Playgroud)

Swift代码(调用代码)

UIView.objcExtensionFunc()
Run Code Online (Sandbox Code Playgroud)


小智 11

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

  • 我是个白痴.我正在添加类名,然后附加"-Swift".原来它是"模块"的名称.+1让我意识到这一点. (10认同)
  • 另一个白痴认为这是班级名称! (2认同)

bra*_*ray 9

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

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


Svi*_*ana 8

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

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


Nic*_* S. 7

对于 Swift 5:

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

    @objc
    public class MyClass: NSObject {
    
        @objc
        public func myMethod() {
    
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Dar*_*kas 6

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

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

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


vik*_*ati 5

有两个条件,

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

因此,为此,您必须执行以下步骤:

  • 将您的swift文件添加到Objective-C项目中,反之亦然。
  • 创建头文件(.h)。
  • 转到“ 构建设置”,然后执行以下搜索步骤,

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

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

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

在这种情况下,请先在班级前的swift文件中输入“ @objc”。

之后,在您的目标c文件中,编写此代码,

  #import "YourProjectName-Swift.h"
Run Code Online (Sandbox Code Playgroud)

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

在这种情况下,请在您的头文件中编写此代码,

  #import "YourObjective-c_FileName.h"
Run Code Online (Sandbox Code Playgroud)

我希望这能帮到您。


归档时间:

查看次数:

146889 次

最近记录:

5 年,10 月 前