Objective-C类中的Swift协议

时间:2014-08-12 13:54:45

标签: objective-c swift

我在Swift中编写了SearcherProtocol,需要实现一个必须使用此协议的Objective-C类FileSearcher

所以我尝试了这个:

#import <Foundation/Foundation.h>

@interface FileSearcher : NSObject <SearcherProtocol>

// ... class content

@end

编译器告诉我

  

找不到&#39; SearcherProtocol&#39;

的协议声明

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

SearcherProtocol导入FileSearcher.h会引发另一个编译错误:module name-swift.h file not found

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

我正在使用Xcode 6 Beta 5.

修改

以下是Swift中的协议声明:

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

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

SearchCompletedProtocol:

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

6 个答案:

答案 0 :(得分:31)

发生这种情况有两个常见原因:

  1. 获取模块名称错误,请参阅我的回答。
  2. 有一个循环参考 - 见下面的mitrenegades答案。
  3. <强> 1。获取模块名称:

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

    对于Xcode6 beta 5,您可以在BuildSettings-&gt; Packaging-&gt;产品模块名称下找到它

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

    如果模块名称有空格,则会出现进一步的错误,这些错误应替换为下划线。

    编辑:

    通过您的协议,我创建了一个名为“测试”的测试项目。编译完美,它有文件:

    TestObjClass.h

    #import <Foundation/Foundation.h>
    #import "Test-Swift.h"
    
    @interface TestObjCClass : NSObject <SearcherProtocol>
    
    @end
    

    TestObjClass.m

    #import "TestObjCClass.h"
    
    
    @implementation TestObjCClass
    
    @end
    

    TestProtocol.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。避免循环引用:

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

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

答案 1 :(得分:22)

当你有

#import "moduleName-Swift.h" 
在你希望成为委托的.h文件中的

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

我最好的方法是组合objc文件,这些文件需要是swift编写的类的委托,但是还需要包含在桥接头中,以便其他swift文件可以访问这个objc类,就是创建一个objc:

中的单独协议文件

MyProtocol.h:

@protocol MyDelegate <NSObject>

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

@end

ViewController.h:

#import "MyProtocol.h"

@interface ViewController : UIViewController <MyDelegate>

MyProject的桥接-Header.h

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

答案 2 :(得分:19)

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

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

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

到此:

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

我还不完全确定我为什么需要&#39; Public&#39;但似乎没有其他人,但嘿,它有效...

答案 3 :(得分:1)

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

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

#import "MyTarget-Swift.h"

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

答案 4 :(得分:-2)

在.h文件

中导入委托
@protocol AnalyticProtocol;

并将其添加到.swift文件

@objc public protocol AnalyticProtocol {

}

答案 5 :(得分:-3)

尝试将#import "Product_Module_Name-Swift.h"添加到Product_Module_Name-Prefix.pch文件中。这对我来说是固定的,而且你现在可以从任何objc文件访问你的swift文件。