Соответствие протоколу Swift из экземпляра протокола Objective C
Я ищу способ динамически сопоставить Objective-C Protocol
экземпляр с соответствующим протоколом Swift.
У меня есть протокол, определенный в Swift, который совместим с Objective-C:
@objc(YHMyProtocol) protocol MyProtocol { }
Я пытаюсь выполнить матч, в функции:
public func existMatch(_ meta: Protocol) -> Bool {
// Not working
if meta is MyProtocol {
return true
}
// Not working also
if meta is MyProtocol.Protocol {
return true
}
return false
}
Эта функция предназначена для вызова из файла Objective-C:
if([Matcher existMatch:@protocol(YHMyProtocol)]) {
/* Do Something */
}
existMatch
функция всегда возвращает false.
Я не могу понять, как решить эту проблему. Я что-то упустил в реализации?
1 ответ
Protocol
непрозрачный тип объекта Это определено в сгенерированном заголовке как:
// All methods of class Protocol are unavailable.
// Use the functions in objc/runtime.h instead.
OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0, 2.0)
@interface Protocol : NSObject
@end
Это не соответствует MyProtocol
, так is MyProtocol
не может работать И, хотя Свифт может неявно мост @objc
протокол метатипов к Protocol
кажется, что он не может сделать обратное; вот почему is MyProtocol.Protocol
не работает (но даже если бы это было, это не будет работать для производных протоколов; как P.Protocol
типы в настоящее время могут содержать только значение P.self
).
Если вы хотите проверить это meta
тип протокола, который эквивалентен или происходит от MyProtocol
, вы можете использовать функцию времени выполнения Obj-C protocol_conformsToProtocol
:
@objc(YHMyProtocol) protocol MyProtocol { }
@objc protocol DerviedMyProtocol : MyProtocol {}
@objc class Matcher : NSObject {
@objc public class func existMatch(_ meta: Protocol) -> Bool {
return protocol_conformsToProtocol(meta, MyProtocol.self)
}
}
// the following Swift protocol types get implicitly bridged to Protocol instances
// when calling from Obj-C, @protocol gives you an equivalent Protocol instance.
print(Matcher.existMatch(MyProtocol.self)) // true
print(Matcher.existMatch(DerviedMyProtocol.self)) // true
Если вы просто хотите проверить это meta
эквивалентно MyProtocol
, ты можешь использовать protocol_isEqual
:
@objc class Matcher : NSObject {
@objc public class func existMatch(_ meta: Protocol) -> Bool {
return protocol_isEqual(meta, MyProtocol.self)
}
}
print(Matcher.existMatch(MyProtocol.self)) // true
print(Matcher.existMatch(DerviedMyProtocol.self)) // false