Objective-C 类中的 Swift 协议

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25266137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:24:36  来源:igfitidea点击:

Swift protocol in Objective-C class

objective-cswift

提问by Alex

I wrote SearcherProtocolin Swift and need to implement an Objective-C class FileSearcherwhich has to use this protocol.

SearcherProtocol用 Swift编写,需要实现一个FileSearcher必须使用这个协议的 Objective-C 类。

So I tried this:

所以我试过这个:

#import <Foundation/Foundation.h>

@interface FileSearcher : NSObject <SearcherProtocol>

// ... class content

@end

The compiler tells me

编译器告诉我

Cannot find protocol declaration for 'SearcherProtocol'

找不到“SearcherProtocol”的协议声明

The corresponding bridged header file (modulename-Swift.h) is being imported within FileSearcher.m.

相应的桥接头文件 ( modulename-Swift.h) 正在FileSearcher.m.

Importing SearcherProtocolinto FileSearcher.hthrows another compiler error: module name-swift.h file not found

导入SearcherProtocolFileSearcher.h抛出另一个编译器错误:module name-swift.h file not found

Does anybody have any clue what I'm doing wrong?

有人知道我做错了什么吗?

I'm using Xcode 6 Beta 5.

我正在使用 Xcode 6 Beta 5。

Edit

编辑

Here is the protocol declaration in Swift:

这是 Swift 中的协议声明:

@objc protocol SearcherProtocol
{    
    var searchNotificationTarget: SearchCompletedProtocol? { get }
    var lastSearchResults: [AnyObject] { get set }

    func search(searchParam: String, error: NSErrorPointer) -> Bool
}

And the SearchCompletedProtocol:

和 SearchCompletedProtocol:

@objc protocol SearchCompletedProtocol
{
    func searchCompletedNotification(sender: AnyObject!)
}

采纳答案by james_alvarez

There are two common reasons for this occuring:

出现这种情况有两个常见原因:

  1. Getting the module name wrong, see my answer.
  2. Having a circular reference - see mitrenegades answer below.
  1. 获取模块名称错误,请参阅我的答案。
  2. 有一个循环引用 - 请参阅下面的 mitrenegades 答案。

1. Get the module name right:

1.正确获取模块名称:

If both the swift protocol and and Objective C are in the same project then according to appleyou should just need to make sure you get the correct module name.

如果 swift 协议和 Objective C 都在同一个项目中,那么根据苹果的说法,您只需要确保获得正确的模块名称。

For Xcode6 beta 5 you can find it under BuildSettings->Packaging->Product Module Name

对于 Xcode6 beta 5,您可以在 BuildSettings->Packaging->Product Module Name 下找到它

A common mistake would be to think that each swift file/class gets its own file, but instead they are all put into one big one that is the name of the project.

一个常见的错误是认为每个 swift 文件/类都有自己的文件,而是将它们全部放入一个大文件中,即项目名称。

A further mistakes are if the module name has spaces, these should be replaced with underscores.

另一个错误是如果模块名称有空格,则应将其替换为下划线。

Edit:

编辑:

With your protocol I created a test project called 'Test' which compiles perfectly and it has the files:

使用您的协议,我创建了一个名为“Test”的测试项目,它可以完美编译并包含以下文件:

TestObjClass.h

测试对象类.h

#import <Foundation/Foundation.h>
#import "Test-Swift.h"

@interface TestObjCClass : NSObject <SearcherProtocol>

@end

TestObjClass.m

TestObjClass.m

#import "TestObjCClass.h"


@implementation TestObjCClass

@end

TestProtocol.swift

测试协议.swift

import Foundation

@objc protocol SearcherProtocol
{
    var searchNotificationTarget: SearchCompletedProtocol? { get }
    var lastSearchResults: [AnyObject] { get set }

    func search(searchParam: String, error: NSErrorPointer) -> Bool
}

@objc protocol SearchCompletedProtocol
{
    func searchCompletedNotification(sender: AnyObject!)
}

2. Avoid circular reference:

2.避免循环引用:

Mitrenegades answer explains this, but if your project needs to use the explicit objc class that uses the swift protocol, (rather than just using the protocol) then you will have circularity issues. The reason is that the swift protocol is defined to the swift-objc header, then to your obj-c class definition, which then goes again to the swift-objc header.

Mitrenegades 的回答对此进行了解释,但是如果您的项目需要使用使用 swift 协议的显式 objc 类(而不仅仅是使用该协议),那么您将遇到循环问题。原因是 swift 协议被定义到 swift-objc 头文件,然后是你的 obj-c 类定义,然后又是 swift-objc 头文件。

Mitrenegades solution is to use an objective-c protocol, is one way, but if you want a swift protocol, then the other would be to refactor the code so as to not use the objective-c class directly, but instead use the protocol (e.g. some protocol based factory pattern). Either way may be appropriate for your purposes.

Mitrenegades 的解决方案是使用objective-c 协议,这是一种方法,但如果你想要一个swift 协议,那么另一种方法是重构代码,以便不直接使用objective-c 类,而是使用协议(例如一些基于协议的工厂模式)。无论哪种方式都可能适合您的目的。

回答by mitrenegade

When you have

当你有

#import "moduleName-Swift.h" 

in the .h file that you want to be a delegate, and you have that .h file also in the bridging headers file, there's a circular reference that causes the moduleName-Swift.h to fail compilation. for @james_alvarez's test project, it's probably working because you don't need to include TestObjClass.h into the bridging header.

在要成为委托的 .h 文件中,并且在桥接头文件中也有该 .h 文件,有一个循环引用会导致 moduleName-Swift.h 编译失败。对于@james_alvarez 的测试项目,它可能有效,因为您不需要将 TestObjClass.h 包含到桥接头中。

The best way for me to combine objc files that need to be the delegate for a class written in swift, but that also needs to be included in the bridging header so other swift files can access this objc class, is to create a separate protocol file in objc:

对我来说,组合需要作为 swift 编写的类的委托的 objc 文件的最佳方法是创建一个单独的协议文件在对象中:

MyProtocol.h:

我的协议.h:

@protocol MyDelegate <NSObject>

-(void)didDoThis;
-(void)didDoThat;

@end

ViewController.h:

视图控制器.h:

#import "MyProtocol.h"

@interface ViewController : UIViewController <MyDelegate>

MyProject-Bridging-Header.h

MyProject-Bridging-Header.h

#import "MyProtocol.h"
#import "ViewController.h"

回答by ED-209

I know this was a long time ago, but I just struggled with the same problem when adding a protocol to my Swift code, and it wasn't being added to the -Swift.h header file, hence "Cannot find protocol declaration"

我知道这是很久以前的事了,但是在向我的 Swift 代码添加协议时我只是遇到了同样的问题,并且它没有被添加到 -Swift.h 头文件中,因此“找不到协议声明”

The problem was my protocol wasn't marked as Public. I changed my protocol from this:

问题是我的协议没有标记为Public。我从这个改变了我的协议:

@objc protocol MyProtocol { //etc.... }

to this:

对此:

@objc public protocol MyProtocol { //etc.... }

I'm still not entirely sure why I need 'Public' but nobody else seems to, but hey it works...

我仍然不完全确定为什么我需要“公共”,但似乎没有其他人需要,但是嘿它有效......

回答by HughV

Make sure you are including the auto generated Swift header in your ObjectiveC file. It will have the same name as your project module followed by -Swift.h.

确保在 ObjectiveC 文件中包含自动生成的 Swift 头文件。它将与您的项目模块同名,后跟-Swift.h.

For instance if your Project Module is MyTarget, then you would use:

例如,如果您的项目模块是MyTarget,那么您将使用:

#import "MyTarget-Swift.h"

#import "MyTarget-Swift.h"

If you are typing in the import into your Objective C file, it will not autocomplete. You can verify that you have the correct file by Command-clicking on the header after typing it in.

如果您在目标 C 文件中输入导入,它不会自动完成。您可以在输入后通过 Command 键单击标题来验证您是否拥有正确的文件。

回答by Jigar Patel

Import delegate as like this in .h file

在 .h 文件中像这样导入委托

@protocol AnalyticProtocol;

and add this in to .swift file

并将其添加到 .swift 文件中

@objc public protocol AnalyticProtocol {

}

回答by Joshua Goossen

Try adding #import "Product_Module_Name-Swift.h"to your Product_Module_Name-Prefix.pchfile. That fixed it for me, plus you will now have access to your swift files from any objc file.

尝试添加#import "Product_Module_Name-Swift.h"到您的Product_Module_Name-Prefix.pch文件中。这为我修复了它,而且您现在可以从任何 objc 文件访问您的 swift 文件。