We have an ObjC API which receive a Protocol instance and return Any?.
// Imported ObjectiveC API
func resolve(_ p: Protocol) -> Any?
// Swift Side Code
@objc protocol P: NSObjectProtocol {
func hello()
}
func test() {
let p = resolve(P.self) as? P
p?.hello()
}
In Swift side, we'd like to wrap the API to make it more swift-friendly.
func resolve2<T>(_ t: T.Type) -> T? {
return resolve(t) as? T // ❌
return resolve(t.self) as? T // ❌
return resolve(T.self) as? T // ❌
// ✅ Currently, I have to use the following code to make it compile
// IMO, maybe I have to constraint T to be a protocol.
// But I do not know how to express it in Swift
guard let tt = NSProtocolFromString(NSStringFromClass(t.self)) else {
return nil
}
return resolve(tt) as? T
}
// ✅ Or we must pass `P.self` twice on the caller side
func resolve3<T>(_ t: T.Type, _ t2: Protocol) -> T? {
return resolve(t2) as? T
}
func test() {
let p1 = resolve2(P.self)
p1?.hello()
let p2 = resolve3(P.self, P.self)
p2?.hello()
}
Before the macro feature landed on Swift, how can I implement resolve2 properly without the dynamic NSXX call or pass P.self twice on the caller side?
Metatypes Background
Some background context about Swift's metatype
/*
https://swiftrocks.com/whats-type-and-self-swift-metatypes.html
```swift
protocol P {}
struct A: P {}
```
Value Type
1 Int
Int.self Int.Type
P.self P.Protocol
A.self A.Type: (any P).Type
P.self Protocol // ?
*/
Or anyone can recommend some doc or material about The ObjectiveC Runtime Protocol'?
I can only find it out Protocol | Apple Developer Documentation here and know it looks like to be a class
Is this API constructing a proxy object or something like that?
Swift doesn’t allow directly abstracting over protocols, so this is just not going to import well to Swift. Even in ObjC, it only really works because of ObjC’s very lax type conversions. I would guess that in practice it’s only used with a handful of protocols, though, and just copy-and-pasting a type-safe wrapper that returns a particular kind of proxy is probably the easiest thing to do.