从Objective-C类调用Swift函数


84

我有一个旧的Objective-C项目,我想调用新的Swift函数和对象,我已经创建了文件“ <ProjectName>-Bridging-Header.h”和“ <ProjectName>-Swift.h

对我来说,从Swift调用函数到Objective-C很容易,但是我有一个反向问题。

因此,我创建了一个简单的类“ System.Swift”

import Foundation

@objc class System : NSObject {

    @objc func printSome() {
        println("Print line System");
    }
    
}

现在我尝试按照此处<...>-Swift.h文件内的文档进行操作

@class System;

@interface System : NSObject

-(void)printSome;

@end

并且已将其导入到Objective-C类中。此时,在我的Objective-C代码的Objective C类(当前为UIViewController)内部,我尝试调用“ printSome”方法:

- (void)viewDidLoad
{
    [super viewDidLoad];
    System * sis = [[System alloc] init];
    [sis printSome];
    //any additional setup after loading the view from its nib.
}

现在我有以下错误:

体系结构i386的未定义符号:“ OBJC_CLASS $ _System”,引用自:“ ObjectiveC_Class_That_Call_Swift_Object”中的objc-class-ref。 -v查看调用)


您有一个链接器错误。是:(1)在命名Objective-C桥接标头和Swift代码的生成标头时,Xcode使用您的产品模块名称,而不是目标名称,或者(2)确保为这些标样导入Objective-C标头在将Swift生成的标头导入到想要从中访问Swift代码的Objective-C .m文件之前,先键入哪种类型?您是否有:在Objective-C代码中#import“ ProductModuleName-Swift.h”?
彼得2014年

是的,我已经阅读了文档,并且“ ProductModelName”的名称已正确显示。存在一个错误,即在“构建设置”中未设置产品模型...我什至设置了它……
Eloreden

@petert您能更好地解释第二点吗?我写过我所做的一切...
Eloreden 2014年

解决了问题,我在项目调用<ProductModelName> -Swift.h中添加了一个新的.h文件,但这不是必需的,因为即使我看不到它,编译器也只会创建该对象。我已经删除了自己创建的新文件,现在一切运行正常。Tnx Petert
Eloreden 2014年

您可以回答自己的问题-可能会对他人有所帮助。
彼得2014年

Answers:


50

解决了问题,我以前.h在我的Objective-C类中创建了一个新文件并将其包含在其中,<ProductModuleName>-Swift.h但是,正如我稍后发现的,此步骤不是必需的,因为编译器会创建不可见的必需文件。

只需将<ProductModuleName>-Swift.h它包括在您的课程中,它就可以正常工作。


3
带参数的函数呢?
Arnlee Vizcayno 2014年

3
我无法使用带有参数和返回值的Swift函数,也无法在没有参数和没有返回值的情况下访问Swift函数。我不知道为什么 我的Swift类是一个NSObject,我导入了Foundation框架,该类和函数具有@objc前缀。在-Swift.h已自动创建。让我头疼的是,我可以调用类本身,但不能调用其中的任何函数。有人知道为什么吗?
DavidGölzhäuser2014年


2
<productModuleName>-.Swift.h(不是model)。
SwiftArchitect

2
如果您的产品名称中包含空格,请用下划线替换,例如:#import "My_Project-Swift.h"
EricRobertBrewer '16

41

这很奇怪,但是会起作用

1) Add @objc  to  Swift class

2) Add in .m 
    #import "(ProjectName)-Swift.h"

3) Call from .h
    @class SwiftClass;

4)On SwiftClass 
   click "Command" + Left Click (Apple Documantation)

5) To see "-Swift.h" -> click "Command" + Left Click

应用程序将在-Swift.h中生成此类的接口

示例:SWIFT_CLASS(“ _ TtC10Project17220PLHelper”)@interface PLHelper

  • (void)notifyForDownloading:(NSDictionary *)userInfo;
  • (instancetype)init OBJC_DESIGNATED_INITIALIZER; @结束

您还可以使用@objc (MyClassName)
nielsbot

12
对于任何可能做与我一样愚蠢的错误的人。在第2步中,请确保使用(ProjectName)-Swift.h,而不是 (ClassName)-Swift.h
Hlung 2015年

谢谢@Svitlana,令人难以置信,它有效了!!!但是我必须重试这些步骤很多次,包括将添加的方法移至类中的其他位置。
Scofield Tran

1
3) @class SwiftClassName;救了我
Mazen Kasser,

33

假设我们有ProjectName“ MyFirstProjectOnSwift”和swift类名称“ mySwiftClass”,而ObjectiveC类是“ MyObjectiveCLass”

以下步骤是:-

  1. 在“ MyObjectiveCLass.m”中添加#import“ MyFirstProjectOnSwift-Swift.h”

  2. 在MyObjectiveCLass.h中添加@class mySwiftClass;

  3. 然后在MyObjectiveCLass.m中

    mySwiftClass * myClass = [mySwiftClass新]; {无论您要调用swift方法如何,都可以通过这种方法调用Like this。}

  4. [myClass methodName];


2
mySwiftClass * myClass = [mySwiftClass new]对我不起作用>>>>>
Hari Narayanan

@HariNarayanan不应该这样,做一个想清楚派生的数据并重新打开您的项目。
Anubhav Giri


2

如果即使在导入后您仍未看到您的班级<ProductModuleName>-Swift.h

确保您的类是本机类的子类(例如UIViewController),或者至少如果它只是一个实用类,请将其设为subclass NSObject。您的班级现在应该显示。


2

对于任何绊倒这篇文章的人来说,没有什么其他提示,对于其他答案也不起作用:您可能还必须将Swift类声明为“ public”。

例:

@objc public class MySwiftClass: NSObject {


0

在从Obj-C迁移到Swift的项目上从Objective-C执行Swift代码的推荐方法是使用Bridge / Proxy模式。

  1. 实施桥梁。

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. 将objC调用者模块包括在伞形文件(Bridging-Header)中:

#import "CallerModule.h"

  1. 最后在调用者.m文件中,出现两个问题:

3.a导入伞形文件:

#import "MyProject-Swift.h"

3.b呼叫网桥。

[[AnalyticsPropertyBridge new] refreshProperties];

好处:因为从Objc调用了代码,所以@objc不会使您的快速代码变得肮脏。随着时间的流逝,ObjC将在您的项目中减少,最后新娘将被移除。


-1

如果有人仍然有问题,可以在这里写一篇好文章。

设置Swift和Objective-C互操作性

  1. 本文深入讨论了如何将Swift文件导入ObjC以及将Objc文件导入Swift。
  2. 它还解决了项目名称中带有空格时通常会遇到的问题。
  3. 它还讨论了“产品模块名称”标志。

尽管从理论上讲这可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。
Arghya Sadhu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.