【问题标题】:Matching a Swift protocol from an Objective-C Protocol instance匹配来自 Objective-C 协议实例的 Swift 协议
【发布时间】:2017-07-10 11:58:04
【问题描述】:

我正在寻找一种将 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。

我不知道如何解决这个问题。我在实施过程中遗漏了什么吗?

【问题讨论】:

  • 您是否要检查meta 是否严格等同于MyProtocol,或者是否等同于或派生自MyProtocol
  • 我想测试 meta 是否兼容/符合MyProtocol

标签: objective-c swift bridging


【解决方案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不能工作。而且,尽管 Swift 可以隐式地将 @objc 协议元类型桥接到 Protocol,但它似乎不能反过来;这就是为什么is MyProtocol.Protocol 不起作用(但即使它起作用,它也不适用于派生 协议;因为P.Protocol 类型目前只能保存值P.self)。

如果要检查meta 是否是与MyProtocol 等效或派生自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

【讨论】:

  • 就是这样!我没有怀疑这些功能的存在。感谢您指出这一点!
  • 乐于帮助@yageek :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多