在Objective-C类中导入Swift协议

Jea*_*ent 108 objective-c swift

我尝试导入一个名为AnalyticProtocolObjective-C类的Swift协议AnalyticFactory.

protocol AnalyticProtocol
{

}
Run Code Online (Sandbox Code Playgroud)

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

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

苹果公司的文件,他们说我,包括我的.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.
}
Run Code Online (Sandbox Code Playgroud)

我想我不明白如何将Swift协议导入Objective-C类.

有谁看到我正在做的错误?

Jam*_*est 206

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

@objc protocol AnalyticProtocol {

}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的回答,但问题仍然存在. (24认同)
  • @objc并不总是有效.当符合协议时,有时它在`.h`文件中的`@interface`上添加协议时不起作用.但是,您可以将协议添加到`.m`文件中的私有`@interface`并修复一些事情(至少它偶尔适用于我).所以你的`@ implementation`上面有`@interface MyController()<AnalyticProtocol>`. (17认同)

Pel*_*tau 72

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

因此,既然你想在objC头文件中使用Swift代码,你需要在objC头文件中"转发声明"你想要使用的类和协议,如下所示:

@protocol AnalyticProtocol;
Run Code Online (Sandbox Code Playgroud)

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

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}
Run Code Online (Sandbox Code Playgroud)

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

这也在Apple Docs的 "使用Swift from Objective-C"一节中描述

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

  • 为什么Xcode在编译和工作正常时会显示丢失协议的警告?有什么办法可以删除警告吗? (16认同)

Chr*_*let 45

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

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

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

    #import "ProductModuleName-Swift.h"
    
    @interface AnalyticFactory () <AnalyticProtocol>
    
    @end
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 这对我有用; 此页面上没有其他建议或答案.我在Swift 4上. (2认同)
  • 这确实为我消除了警告,但是编译时出现错误,因为使用采用 Swift 协议的 ObjC 文件的 swift 类无法看到 ObjC 文件正在采用该协议! (2认同)
  • 通过 WebArchive 可以获得相同的链接:https://web.archive.org/web/20170310053717/https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html (2认同)
  • 注意:如果使用此方法仍然收到构建警告,请确保协议未在 ObjC .h 文件中前向声明。此外,您不能在头文件中将类标记为符合协议。只要协议仅以 .m 形式出现,您就一切就绪。 (2认同)

Vin*_*ane 8

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

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

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

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}
Run Code Online (Sandbox Code Playgroud)

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

@protocol ObjTableViewReloadable;
Run Code Online (Sandbox Code Playgroud)

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

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>
Run Code Online (Sandbox Code Playgroud)


Mic*_*hal 5

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

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

更改为:

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

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

@objc public protocol AnalyticProtocol {
  func something();
}
Run Code Online (Sandbox Code Playgroud)