簡體   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