Objective-C类中的Swift协议

Ale*_*lex 39 objective-c swift

SearcherProtocol在Swift中写道,需要实现一个FileSearcher必须使用这个协议的Objective-C类.

所以我尝试了这个:

#import <Foundation/Foundation.h>

@interface FileSearcher : NSObject <SearcherProtocol>

// ... class content

@end
Run Code Online (Sandbox Code Playgroud)

编译告诉我

找不到'SearcherProtocol'的协议声明

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

导入SearcherProtocolFileSearcher.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
}
Run Code Online (Sandbox Code Playgroud)

而SearchCompletedProtocol:

@objc protocol SearchCompletedProtocol
{
    func searchCompletedNotification(sender: AnyObject!)
}
Run Code Online (Sandbox Code Playgroud)

jam*_*rez 32

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

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

1.获取模块名称:

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

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

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

进一步的错误是模块名称有空格,这些应该用下划线替换.

编辑:

使用您的协议,我创建了一个名为"Test"的测试项目,该项目完美编译并具有以下文件:

TestObjClass.h

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

@interface TestObjCClass : NSObject <SearcherProtocol>

@end
Run Code Online (Sandbox Code Playgroud)

TestObjClass.m

#import "TestObjCClass.h"


@implementation TestObjCClass

@end
Run Code Online (Sandbox Code Playgroud)

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!)
}
Run Code Online (Sandbox Code Playgroud)

2.避免循环引用:

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

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


mit*_*ade 23

当你有

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

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

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

MyProtocol.h:

@protocol MyDelegate <NSObject>

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

@end
Run Code Online (Sandbox Code Playgroud)

ViewController.h:

#import "MyProtocol.h"

@interface ViewController : UIViewController <MyDelegate>
Run Code Online (Sandbox Code Playgroud)

MyProject的桥接,Header.h

#import "MyProtocol.h"
#import "ViewController.h"
Run Code Online (Sandbox Code Playgroud)


ED-*_*209 19

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

问题是我的协议没有标记为公共.我改变了我的协议:

@objc protocol MyProtocol { //etc.... }
Run Code Online (Sandbox Code Playgroud)

对此:

@objc public protocol MyProtocol { //etc.... }
Run Code Online (Sandbox Code Playgroud)

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