繁体   English   中英

Swift 在面向协议的编程中向 objc 公开协议

[英]Swift expose the protocol to objc in protocol oriented programming

我有这个运行良好的代码:

public protocol PermissionProvider {
  static func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus
}
extension AVCaptureDevice: PermissionProvider {}

现在我需要将协议暴露给 Objc 运行时:

@objc // added this attribute
public protocol PermissionProvider {
  static func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus
}
extension AVCaptureDevice: PermissionProvider {}

但我收到一条错误消息:

AVFoundation.AVCaptureDevice:4:21: error: Objective-C method 'authorizationStatusForMediaType:' provided by method 'authorizationStatus(for:)' does not match the requirement's selector ('authorizationStatusFor:')
    open class func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus

从错误消息来看,它似乎与 objc 和 swift 之间的一些命名约定有关。 我想知道如何修复编译错误?

我引入这个协议的原因是,我需要对这个“权限提供者”进行单元测试和注入。 而我需要将其暴露给 objc 的原因是,一些调用者仍在 ObjC 中

编辑:

我创建了一个空项目,然后用上面的代码创建了一个新文件,并得到了错误

在此处输入图像描述

在协议方法上添加 @objc 属性以指定要暴露给 Objective-C 的不同方法名称,在这种情况下,将其与AVCaptureDevice的相关方法( authorizationStatusForMediaType: :)匹配:

@objc // added this attribute
public protocol PermissionProvider {
    @objc(authorizationStatusForMediaType:) static func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus
}
extension AVCaptureDevice: PermissionProvider {}

为什么?

当 Objective-C 方法映射到 Swift 时,与相应参数类型匹配的参数描述会被删减(参见SE-0005 'Better Translation of Objective-C APIs into Swift' ),但是当 Swift 映射到 Objective-C 时相应的“去修剪”不会发生。

例如,如果在 Objective-C 中我们定义了:

- (NappingStatus)nappingStatusForKoala:(Koala *)koala;

- (NappingStatus)nappingStatusForEchidna:(Koala *)koala;

当映射到 Swift 中时,这些将变为:

func nappingStatus(for: Koala) -> NappingStatus

func nappingStatus(forEchidna: Koala) -> NappingStatus

请注意,在第一种方法中, Koala已从参数名称中删除,因为它与它所描述的参数类型匹配,但在第二种方法中, Echidna没有被删除,因为它与参数的类型不匹配。描述(考拉)。

当从 Swift 映射到 Objective-C 时,这种修剪的逆转不会发生。 例如,如果在 Swift 中我们定义了

func nappingStatus(for: Koala) -> NappingStatus

当映射到 Objective-C 时,它将变为:

- (NappingStatus)nappingStatusFor:(Koala *)koala;

因此,对于您的情况,Objective-C 中的 AVCaptureDevice 方法是:

+ (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType;

在 Swift 中被映射到(注意 MediaType 被修剪):

class func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus

但是您的协议方法,在 Swift 中是:

static func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus

当映射到 Objective-C 时将是(注意 MediaType 不是 `de-pruned'):

+ (AVAuthorizationStatus)authorizationStatusFor:(AVMediaType)mediaType;

这与 AVCaptureDevice 中的 Objective-C 方法不匹配,因此我们只需通过 @objc 属性提供正确的 Objective-C 方法名称:

@objc(authorizationStatusForMediaType:) static func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM