在Objective-C类中导入Swift协议


115

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

protocol AnalyticProtocol
{

}

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

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

他们在Apple文档中说,我必须在.h文件MyProjectName-Swift.h中包含命名的.m文件。但是我需要不将其包括在.m文件中,而是将其包括在文件中.h。这可能有问题吗?

当我尝试编译时,出现以下错误:: 0:错误:xxxAnalyticFactory.h:39:找不到“ AnalyticProtocol”的协议声明

并包含以下代码:

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

我想我不太了解如何将Swift协议导入Objective-C类。

有人在我做的事情中看到错误吗?


观看WWDC 2014中的将Swift与Objective-C集成视频。在视频中大约30:40,他们描述了如何在Objective-C类中访问Swift协议。
Jamie Forrest 2014年

Answers:


224

您需要@objc像这样将属性添加到您的Swift协议中:

@objc protocol AnalyticProtocol {

}

25
感谢您的回答,但问题仍然存在。
Jean Lebrument 2014年

您能否发布一个重现该问题的示例项目?
Jamie Forrest 2014年

添加@objc帮助我将Swift类导入到Obj-C中
serg 2014年

19
@objc并不总是有效。遵循协议时,有时在将协议添加@interface.h文件中时不起作用。但是,您可以将协议添加到私人@interface的在.m文件,并将其固定的东西(至少对我来说偶尔)。所以你上面的@implementation@interface MyController() <AnalyticProtocol>
亚当

1
有时Xcode 8在您编辑时会抱怨,但是当您实际构建它时,遵循此答案以及注释,该错误将消失。
罗杰·平格尔顿

77

无法在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编译器现在将知道正确的实现。

Apple Docs中的 “在Objective-C中使用Swift”部分也对此进行了描述。

请注意,当您使用正向声明的协议(“找不到'AnalyticProtocol'的协议定义)时,XCode会在objC头文件中发出警告,但这可以忽略-实现将在编译时找到。


19
为什么Xcode在编译和正常工作时会显示缺少协议的警告?有什么办法可以消除警告?
奥伦

不过,仍然无法在此类上调用协议方法。它将给出错误No visible @interface for <ClassName> declares the selector <protocolMethodName>
Elsa,

它会产生以下警告:“找不到xxxx的协议定义”
JAHelia

51

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

  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


1
无论是否进行前向声明,我仍然会收到警告。我在扩展程序中使用该协议。
Cristi Băluță

无法导入#import "AnalyticProtocol-Swift.h"。看起来WhateverProtocol-Swift.h不会像您所说的那样自动生成。
Hlung

2
这对我有用;此页面上没有其他建议或答案。我对雨燕4
Poulsbo的

1
这是消除警告的唯一方法(即使协议在头文件中也可以使用)
David P


3

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

#import "ProductModuleName-Swift.h"

更改为:

#import <ProductModuleName/ProductModuleName-Swift.h>

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

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

3

我们可以在目标C中使用快速协议,而无需更改代码。同样,@ objc声明的协议使您可以使用可选方法和必需方法,而无需默认实现。它具有优点和缺点。

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

这是代码,让我们有一个带有@objc属性和别名的快速协议,可以在ObjC代码中使用。

@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>

感谢您发布此信息。我正在查看比污垢更旧的旧代码,如果这种方法行得通,它将为我省去很多麻烦。:)
Adrian
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.