【问题标题】:Call Swift function from Objective-C class从 Objective-C 类调用 Swift 函数
【发布时间】:2014-07-27 12:00:27
【问题描述】:

我有一个旧的 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");
    }
    
}

现在我尝试遵循文档 here 并在 <...>-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.old:未找到架构 i386 的符号:错误:链接器 命令失败,退出代码为 1(使用 -v 查看调用)

【问题讨论】:

  • 您有一个链接器错误。是不是:(1) Xcode 在命名 Objective-C 桥接头和为 Swift 代码生成的标头时使用您的产品模块名称而不是目标名称,或者 (2) 确保为那些导入 Objective-C 标头在将 Swift 生成的标头导入到 Objective-C .m 文件之前的类型,您想从中访问 Swift 代码?您的 Objective-C 代码中是否有:#import “ProductModuleName-Swift.h”?
  • 是的,我已经阅读了文档并且“ProductModelName”的名称是正确的......在构建设置中存在一个错误,产品模型没有设置......我什至设置了它。 ..
  • @petert 你能更好地解释第二点吗?我写了我所做的一切......
  • 问题已解决,我在我的项目调用中添加了一个新的 .h 文件 -Swift.h 但这不是必需的,因为即使我看不到它,编译器也会创建这个对象.我已经删除了我创建的新文件,现在一切运行良好。 Tnx 彼得
  • 您可以回答自己的问题 - 这可能对其他人有所帮助。

标签: objective-c swift


【解决方案1】:

问题已解决,我之前在名为 <ProductModuleName>-Swift.hObjective-C 类中创建并包含了一个新的 .h 文件,但正如我后来发现的那样,这一步不是必需的,因为编译器会创建必要的文件不可见。

只需在您的课程中包含<ProductModuleName>-Swift.h,它应该可以工作。

【讨论】:

  • 带参数的函数怎么样?
  • 我无法访问带有参数和返回值的 Swift 函数,也无法访问没有参数和返回值的 Swift 函数。我不知道为什么。我的 Swift 类是一个 NSObject,我导入了 Foundation 框架,类和函数都有 @objc 前缀。 -Swift.h 已自动创建。让我头疼的是,我可以调用 Class 本身,但不能调用其中的任何函数。有谁知道为什么?
  • <productModuleName>-.Swift.h(不是model)。
  • 如果您的产品名称中有空格,请用下划线替换它们,例如:#import "My_Project-Swift.h"
【解决方案2】:

这很奇怪,但在我们这样做之后会起作用:

  1. @objc 添加到您的 Swift 类(“MySwiftClass”)。

  2. 添加Obj-C,即.m文件:

    #import "(ProjectName)-Swift.h"
    
  3. 在头文件.h中声明

    @class MySwiftClass;
    

编译器将为MyModuleName-Swift.h文件中的@objc标记类生成接口。

自动生成的 Obj-C 示例:

SWIFT_CLASS("_TtC10Project17220PLHelper")
@interface PLHelper

+ (void)notifyForDownloading:(NSDictionary *)userInfo;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

【讨论】:

  • 您还可以使用 @objc (MyClassName) 覆盖您的 Swift 类的 Obj-C 名称
  • 对于任何可能和我犯同样愚蠢错误的人。在第 2 步中,确保使用 (ProjectName)-Swift.hNOT (ClassName)-Swift.h!
  • 感谢@Svitlana,难以置信,它成功了!!!但是我必须多次重试这些步骤,包括将我添加的方法移动到课堂上的其他地方。
  • 3) @class SwiftClassName;救了我
  • 如果您的目标名称有任何 spaces 在创建 swift.h 导入时添加“_”(下划线而不是空格)例如:如果您的目标名称是 Sample App,那么您的导入语句将是 @ 987654335@
【解决方案3】:

检查 -Swift.h 文件,它在 Objective-C 中的 .m 文件中具有导入:

#import <YourProjectName-Swift.h>

单击该行,然后左键单击 - 跳转到定义。

此文件应自动包含,而不是手动包含。

【讨论】:

    【解决方案4】:

    假设我们有 ProjectName "MyFirstProjectOnSwift" 和 swift 类名 "mySwiftClass" 并且 ObjectiveC 类是 "MyObjectiveCLass"

    以下步骤是:-

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

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

    3. 然后在 MyObjectiveCLass.m 中

      mySwiftClass *myClass = [mySwiftClass new]; {像这样在任何 方法,无论你想调用 swift 方法。}

    4. [myClass 方法名];

    【讨论】:

    • mySwiftClass *myClass = [mySwiftClass new] 它不适合我>>>>
    • @HariNarayanan 不应该,想一想清除派生数据并重新打开您的项目。
    【解决方案5】:

    如果您在导入 &lt;ProductModuleName&gt;-Swift.h 后仍然没有看到您的课程。

    确保您的类是本机类的子类(例如UIViewController),或者至少如果它只是一个实用程序类,则使其成为NSObject 的子类。您的课程现在应该显示出来了。

    【讨论】:

      【解决方案6】:

      对于偶然发现这篇文章的任何人以及其他答案不起作用的人的一点额外提示:您可能还必须将您的 Swift 类声明为“public”。

      例子:

      @objc public class MySwiftClass: NSObject {

      【讨论】:

        【解决方案7】:

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

        1. 实施桥梁。

        import Foundation

        @objc class AnalyticsPropertyBridge: NSObject {

        private var analytics: AnalyticsManager = AnalyticsManager()
        
        @objc func refreshProperties() {
        
            self.analytics.set(AnalyticsProperty.clientType)
        }
        

        }

        1. 在伞形文件 (Bridging-Header) 中包含 objC 调用程序模块:

        #import "CallerModule.h"

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

        3.a 导入伞形文件:

        #import "MyProject-Swift.h"

        3.b 调用网桥。

        [[AnalyticsPropertyBridge new] refreshProperties];

        好处:你的swift代码不会被@objc弄脏,因为代码是从Objc调用的。随着时间的推移,你的项目中的 ObjC 会减少,最后会移除新娘。

        【讨论】:

          【解决方案8】:

          如果有人仍有问题,这里是一篇好文章。

          Setting up Swift and Objective-C Interoperability

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

          【讨论】:

          • 虽然理论上这可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
          【解决方案9】:

          关于项目名称的注释,如果项目名称中有空格,请确保将它们替换为下划线,例如如果项目名称是“我的项目”,则需要包括:

          #import <My_Project-Swift.h>
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-01-02
            • 2018-11-10
            • 1970-01-01
            • 2020-06-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多