다음과 같이 정의한 프로토콜이 있습니다.
protocol MyProtocol {
...
}
또한 일반 구조체가 있습니다.
struct MyStruct <T> {
...
}
마지막으로 일반적인 기능이 있습니다.
func myFunc <T> (s: MyStruct<T>) -> T? {
...
}
T 유형이 MyProtocol을 준수하는지 함수 내부를 테스트하고 싶습니다. 본질적으로 나는 할 수 있기를 원합니다 (~ 의사 코드) :
let conforms = T.self is MyProtocol
그러나 이것은 컴파일러 오류를 발생시킵니다.
error: cannot downcast from 'T.Type' to non-@objc protocol type 'MyProtocol'
let conforms = T.self is MyProtocol
~~~~~~ ^ ~~~~~~~~~~
나는 또한 변화 같은 시도 T.self is MyProtocol.self
, T is MyProtocol
그리고 사용하는 ==
대신을 is
. 지금까지 나는 아무데도 가지 않았다. 어떤 아이디어?
답변
@Alex가 T
유형이 아닌 프로토콜을 준수 하는지 확인하고 싶습니다 s
. 그리고 일부 응답자는 명확하게 보지 못했습니다.
확인 T
유형은 다음과 같은 프로토콜을 따릅니다.
if let _ = T.self as? MyProtocol.Type {
// T conform MyProtocol
}
또는
if T.self is MyProtocol.Type {
// T conform MyProtocol
}
답변
조금 늦었지만 테스트로 프로토콜에 응답하는지 테스트 할 수 있습니다 as ?
.
if let currentVC = myViewController as? MyCustomProtocol {
// currentVC responds to the MyCustomProtocol protocol =]
}
편집 : 조금 더 짧게 :
if let _ = self as? MyProtocol {
// match
}
그리고 가드 사용 :
guard let _ = self as? MyProtocol else {
// doesn't match
return
}
답변
가장 간단한 대답은 : 그렇게하지 마십시오. 대신 오버로딩 및 제약 조건을 사용하고 런타임에 동적으로 테스트하는 대신 컴파일 타임에 모든 것을 미리 결정하십시오. 런타임 유형 검사 및 컴파일 타임 제네릭은 스테이크와 아이스크림과 비슷합니다. 둘 다 좋지만 혼합하는 것은 약간 이상합니다.
다음과 같은 것을 고려하십시오.
protocol MyProtocol { }
struct MyStruct <T> { let val: T }
func myFunc<T: MyProtocol>(s: MyStruct<T>) -> T? {
return s.val
}
func myFunc<T>(s: MyStruct<T>) -> T? {
return nil
}
struct S1: MyProtocol { }
struct S2 { }
let m1 = MyStruct(val: S1())
let m2 = MyStruct(val: S2())
myFunc(m1) // returns an instance of S1
myFunc(m2) // returns nil, because S2 doesn't implement MyProtocol
단점은 T가 런타임에 프로토콜을 지원하면 동적으로 설정할 수 없다는 것입니다.
let o: Any = S1()
let m3 = MyStruct(val: o)
myFunc(m3) // will return nil even though o
// does actually implement MyProtocol
그러나 솔직히 말해서 일반 함수 내에서 그렇게해야합니까? 실제 유형이 무엇인지 확실하지 않은 경우 더 나은 옵션은 나중에 지연하고 알아 내기 위해 제네릭 함수 내에서 찌르는 것보다 미리 파악하는 것입니다.
답변
여러 유형의 케이스를 처리하려는 경우 swift의 스위치 케이스 패턴 일치를 활용할 수도 있습니다 T
.
func myFunc<T>(s: MyStruct<T>) -> T? {
switch s {
case let sType as MyProtocol:
// do MyProtocol specific stuff here, using sType
default:
//this does not conform to MyProtocol
...
}
}
답변
준수하자 = T.self는 MyProtocol.Type입니다.
답변
프로토콜을 @objc
다음 과 같이 선언해야합니다 .
@objc protocol MyProtocol {
...
}
Apple의 “The Swift Programming Language”책에서 발췌 :
위의 HasArea 프로토콜에서 볼 수 있듯이 프로토콜이 @objc 속성으로 표시된 경우에만 프로토콜 적합성을 확인할 수 있습니다. 이 속성은 프로토콜이 Objective-C 코드에 노출되어야 함을 나타내며 Cocoa 및 Objective-C와 함께 Swift 사용에 설명되어 있습니다. Objective-C와 상호 운용되지 않더라도 프로토콜 적합성을 확인하려면 @objc 속성으로 프로토콜을 표시해야합니다.
또한 @objc 프로토콜은 구조 나 열거가 아닌 클래스에 의해서만 채택 될 수 있습니다. 적합성을 확인하기 위해 프로토콜을 @objc로 표시하면 해당 프로토콜을 클래스 유형에만 적용 할 수 있습니다.
답변
테스트 케이스의 경우 다음과 같이 적합성을 확인합니다.
let conforms: Bool = (Controller.self as Any) is Protocol.Type