简体   繁体   English

从Objective-C协议实例匹配Swift协议

[英]Matching a Swift protocol from an Objective-C Protocol instance

I'm looking for a way to match dynamically an Objective-C Protocol instance with a corresponding Swift protocol. 我正在寻找一种方法来动态匹配Objective-C Protocol实例与相应的Swift协议。

I have a protocol defined in swift that is compatible with Objective-C: 我在swift中定义了一个与Objective-C兼容的协议:

@objc(YHMyProtocol) protocol MyProtocol { }

I try to perform the match, in a function: 我试着在一个函数中执行匹配:

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
}

This function is intended to be called from an Objective-C file: 此函数旨在从Objective-C文件中调用:

if([Matcher existMatch:@protocol(YHMyProtocol)]) {
    /* Do Something */
}

The existMatch function always returns false. existMatch函数始终返回false。

I can not figure out how to solve this. 我无法弄清楚如何解决这个问题。 Did I miss something in the implementation? 我是否遗漏了实施中的内容?

Protocol is an opaque object type. Protocol是一种不透明的对象类型。 It's defined in the generated header as: 它在生成的头文件中定义为:

// 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

It doesn't conform to MyProtocol , so is MyProtocol cannot work. 它不符合MyProtocol ,因此is MyProtocol无法正常工作。 And, although Swift can implicitly bridge @objc protocol metatypes to Protocol , it appears that it cannot do the reverse; 而且,虽然斯威夫特可以隐桥@objc协议元类型,以Protocol ,看来,它不能做反向; which is why is MyProtocol.Protocol doesn't work (but even if it did, it wouldn't work for derived protocols; as P.Protocol types can currently only hold the value P.self ). 这就是为什么is MyProtocol.Protocol不起作用(但即使它确实如此,它也不适用于派生协议;因为P.Protocol类型目前只能保持值P.self )。

If you want to check that meta is a protocol type that is equivalent to, or derives from, MyProtocol , you can use the Obj-C runtime function protocol_conformsToProtocol : 如果要检查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

If you just want to check that meta is equivalent to MyProtocol , you can use protocol_isEqual : 如果您只想检查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

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

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