【问题标题】:Importing a Swift protocol in Objective-C class在 Objective-C 类中导入 Swift 协议
【发布时间】:2014-06-06 09:15:58
【问题描述】:

我尝试将一个名为 AnalyticProtocol 的 Swift 协议导入到一个名为 AnalyticFactory 的 Objective-C 类中。

protocol AnalyticProtocol
{

}

我从现有的 Objective-C 项目开始(我没有使用 xCode 创建新的 Swift 项目,也没有找到如何在 xCode 6 中将我的 Objective-C 项目配置为 Swift 项目)。

在我的 Swift 文件中,我包含了名为 MyProjectName-Swift.h.h 文件,但编译器返回一个错误,告诉我 它不存在。 所以,我创建了一个名为MyProjectName-Swift.h.h 文件,它实际上是空的(我不知道我应该在里面放什么)。

Apple documentation 中,他们说我必须将名为MyProjectName-Swift.h.h 文件包含在我的.m 文件中。但我需要将它包含在我的.mfile 中,而不是包含在我的.h 中。这会不会有问题?

当我尝试编译时出现以下错误::0: error: xxxAnalyticFactory.h:39: cannot find protocol declaration for 'AnalyticProtocol'

还有涉案代码:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

我想我不太明白如何将 Swift 协议导入到 Objective-C 类中。

有没有人发现我正在做的事情有错误?

【问题讨论】:

标签: objective-c swift


【解决方案1】:

您需要将@objc 属性添加到您的 Swift 协议中,如下所示:

@objc protocol AnalyticProtocol {

}

【讨论】:

  • 感谢您的回答,但问题仍然存在。
  • 您能否发布一个重现该问题的示例项目?
  • 添加 @objc 帮助我将 Swift 类导入到 Obj-C
  • @objc 并不总是有效。当符合协议时,有时在.h 文件中的@interface 上添加协议时不起作用。但是,您可以将协议添加到 .m 文件中的私有 @interface 并修复问题(至少它有时对我有用)。所以在你的@implementation 上面有@interface MyController() &lt;AnalyticProtocol&gt;
  • 有时 Xcode 8 在您编辑时会报错,但是当您实际构建它时,按照这个答案和 cmets 一起,错误就会消失。
【解决方案2】:

无法在 objC 头文件中导入 Xcode 生成的 Swift 头文件。

因此,由于您想在 objC 头文件中使用 Swift 代码,您需要在 objC 头文件中“前向声明”您想要使用的类和协议,如下所示:

@protocol AnalyticProtocol;

您现在可以在 objC 类声明中使用该协议:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

在您的实现文件(objC .m 文件)中,您可以导入 Xcode 生成的 Swift 标头(“ProductModuleName-Swift.h”)文件,编译器现在将知道正确的实现 AnalyticProtocol

这在官方Importing Swift into Objective-C也有描述

请注意,当您使用前向声明的协议时,XCode 会在 objC 头文件中给出警告(“Cannot find protocol definition for 'AnalyticProtocol'),但这可以忽略 - 将在编译时找到实现。

【讨论】:

  • 为什么 Xcode 在编译和工作正常时会显示缺少协议的警告?有什么办法可以消除警告?
  • 但是仍然不能调用这个类的协议方法。它会给出错误No visible @interface for &lt;ClassName&gt; declares the selector &lt;protocolMethodName&gt;
  • 它会产生以下警告:“找不到 xxxx 的协议定义”
【解决方案3】:

对于只需要采用协议的任何人 - 您可以分两步完成此操作,而不会产生任何警告或错误:

  1. 在您的.swift 文件中,在协议名称前添加@objc

    @objc protocol AnalyticProtocol {
    
    }
    
  2. 在您的 .m 文件中,导入生成的 Swift 标头并采用私有类别中的协议。 (头文件自动命名):

    #import "ProductModuleName-Swift.h"
    
    @interface AnalyticFactory () <AnalyticProtocol>
    
    @end
    

这是 Apple 推荐的方法。您可以在此处了解有关混合和匹配 Objective-C 和 Swift 的更多信息:https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

【讨论】:

  • 我仍然收到警告,无论是否提前声明。我在扩展中使用该协议。
  • 这对我有用;此页面上没有其他建议或答案有效。我在 Swift 4 上。
  • 这是删除警告的唯一方法(即使它在协议位于头文件中时有效)
  • 这确实消除了我的警告,但是编译有错误,因为使用采用 Swift 协议的 ObjC 文件的 swift 类看不到 ObjC 文件正在采用协议!
  • 可以通过 WebArchive 获得相同的链接:web.archive.org/web/20170310053717/https://developer.apple.com/…
【解决方案4】:

我们可以在 Objective C 中使用 swift 协议,只需对代码进行少量更改。此外,@objc 声明的协议让您拥有可选和必需的方法,而无需默认实现。它有利有弊。

在 Objective C 中使用时,我们实际上可以将协议名称重命名为更具描述性。我使用“@objc(alias_name)”。

这里是代码, 让我们在 ObjC 代码中使用带有 @objc 属性和别名的 swift 协议。

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}

现在让 farword 在 .h 文件中声明我们的协议

@protocol ObjTableViewReloadable;

您现在可以在 .m 文件中遵守此协议并添加所需的方法实现。

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>

【讨论】:

  • 感谢您发布此信息。我正在查看比污垢更古老的遗留代码,如果这种方法有效,它将为我省去很多痛苦。 :)
  • 嗨,MyApp-Swift.h 的标题是什么?是为包含协议的 Objc 生成的 swift 类头吗?
【解决方案5】:

如果您正在创建框架,则需要导入

#import "ProductModuleName-Swift.h"

更改为:

#import <ProductModuleName/ProductModuleName-Swift.h>

在这种情况下,您还必须将 swift 协议公开

@objc public protocol AnalyticProtocol {
  func something();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2014-12-15
    相关资源
    最近更新 更多