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

所以我try 了这个:

#import <Foundation/Foundation.h>

@interface FileSearcher : NSObject <SearcherProtocol>

// ... class content

@end

编译器告诉我

找不到"SearcherProtocol"的协议声明

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

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

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

我使用的是Xcode 6 Beta 5.

Edit

以下是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!)
}

推荐答案

There are two common reasons for this occuring:

  1. 模块名搞错了,请看我的答案.
  2. 有一个循环参考——见下面的米特伦加德斯答案.

1. Get the module name right:

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

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

一个常见的错误是,认 for each swift文件/类都有自己的文件,但它们都放在一个大文件中,即项目名称中.

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

编辑:

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

TestObjClass.H

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

@interface TestObjCClass : NSObject <SearcherProtocol>

@end

TestObjClass.M

#import "TestObjCClass.h"


@implementation TestObjCClass

@end

测试协议.敏捷的

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:

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

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

Swift相关问答推荐

在Swift中initt()完成后运行一个函数

如何访问用户选定目录下的(只读)文件?

RealityKit(VisionOS)中的PhysicBodyComponent和DragGesture

SwiftUI:使视图B与视图A具有相同宽度的视图A更改比率?

我在SwiftUI中的动画无法正常工作

如何让ScrollView缩小到合适的大小,并在没有黑客攻击的情况下占用最小空间

将 Encodable 扩展添加到 Swift 嵌套枚举

ForEach within List:模式的好处?

使用 Async-Await 和 Vapor-Fluent 创建 CRUD 函数 - Swift 5.6

如何在 SWIFTUI 中旋转修剪?

如何更新 UserDefault 中的特定值

Swift - 订阅视图之外的绑定值

如何确定扩展中的具体类型?

持久化字符串列表属性 RealmSwift

如何在填充上添加 if else 语句? SwiftUI

如何让 UIKit 挤压你的视图,使其适合屏幕

如何使被拖动的对象成为前景(foreground)对象

在 Swift 中将两个字节的 UInt8 数组转换为 UInt16

'#selector' 的参数不引用 '@objc' 方法、属性或初始化程序

将强制向下转换视为可选将永远不会产生零