How to check conformance to protocol with associated type in Swift?
TL;DR
Compiler does not have enough information to compare the type until associated type is set.
When you refer to simple protocol, compiler knows its type from the beginning.
But when you refer to protocol with associated type, compiler doesn't know its type until you declare it.
protocol ExampleProtocol {
associatedtype SomeType
func foo(param: SomeType)
}
At this moment for compiler it looks like this:
protocol ExampleProtocol {
func foo(param: <I don't know it, so I'll wait until it's defined>)
}
When you declare a class conforming to the protocol
class A: ExampleProtocol {
typealias SomeType = String
func foo(param: SomeType) {
}
}
Compiler starts to see it like this:
protocol ExampleProtocol {
func foo(param: String)
}
And then it is able to compare types.
Checking if Any.Type conforms to a protocol in Swift
To check the pure Swift code, you can do:
protocol MySwiftProtocol: AnyObject {
}
class MySwiftClass: MySwiftProtocol {
}
if MySwiftClass.self as? MySwiftProtocol.Type != nil {
print("conforms")
} else {
print("does not conform")
}
or more simply:
if MySwiftClass.self is MySwiftProtocol.Type {
swift how to determine associatedtype in sub protocol
How about
protocol TestProtocol {
associatedtype T: Equatable
}
struct TestProtocolContainer<U: Equatable>: TestProtocol {
typealias T = U
}
struct Test {
let value: TestProtocolContainer<Int>
}
When you declare a protocol with associatedtype
(which offers static polymorphism, If you are interested in understanding various types of polymorphism and how to achieve it with protocol in swift do give a read to my blogpost here).
you cant use that protocol as Concrete type because compiler can't resolve the type of T
during compilation. (Why during compilation, I said its static polymorphism remember :) )
So that's why compiler expects you to provide it someway to help it resolve the type of associatedtype
during compilation. One way is by providing typealias
and specifying the actual data type of associatedtype
.
example :
struct TestProtocolContainer: TestProtocol {
typealias T = Int
}
This works great but then, you would want to make this Generic struct to represent any struct with Equatable
type. Thats where Generics comes into picture.
struct TestProtocolContainer<U: Equatable>: TestProtocol {
This represents a Generic structure which uses any Equatable
type and confirms TestProtocol
and finally setting
typealias T = U
Ensures confirmation to TestProtocol
Hope this helps
returning swift protocol associated type in multiple methods
The solution you came up with by playing around is exactly what you need
As mentioned elsewhere, the main issue with your first protocol is that you're enforcing createSomeView()
createAnotherView()
both return the same type. While ViewA()
and ViewB()
are both candidates for V
, since they conform to View
they are still different types, and therefore cannot BOTH be V
in a given object.
By defining both V1
and V2
, you allow for each function to return a different type, or the same type, it's all acceptable. By making both V1
and V2
require View
conformance, you allow for the some View
syntax
Check if two objects implement a Swift protocol and its associated type
It was trickier than I expected (so I deleted my previous post to avoid confusion) but I believe this should work for you:
protocol ViewModelContainerVC
{
mutating func setModel(_ :Any)
}
protocol ViewModelContainer:class,ViewModelContainerVC
{
associatedtype ViewModelType
var viewModel: ViewModelType! { get set }
}
extension ViewModelContainer
{
mutating func setModel(_ model:Any)
{ if model is ViewModelType { viewModel = model as! ViewModelType } }
}
You can then use the ViewModelContainerVC for type casting and assignment:
if let container = container as? ViewModelContainerVC
{
container.setModel(model)
}
[EDIT] for future reference, here's the same thing with a Bool return for type compatibility:
protocol ViewModelContainerVC
{
@discardableResult mutating func setModel(_ :Any) -> Bool
}
extension ViewModelContainer
{
@discardableResult mutating func setModel(_ model:Any) -> Bool
{
if let validModel = model as? ViewModelType
{ viewModel = validModel; return true }
return false
}
}
Which will allow a combined condition :
if var container = container as? ViewModelContainerVC,
container.setModel(model)
{ ... }
Related Topics
How to Capture Multiple Arguments Weakly in a Swift Closure
Swift Any Difference Between Closures and First-Class Functions
Constant 'Result' Inferred to Have Type (), Which May Be Unexpected
Swift 3: Safe Way to Decode Values with Nscoder
Swift/Cloudkit: After Record Changed, Upload Triggers "Service Record Changed"
Phase 1 and Phase 2 Initialization in Swift
How to Switch an Xcode Project to Use Swift Version 1.2 in the Xcode 7 Beta
Firebasecore Lexical or Preprocessor Issue
Notification Extension Access Core Data
How to Submit Swift 2.2 App with Xcode 7.3 When iOS 10 Is Released
How to Prevent Multiple Instances of the Same Window from Opening in MACos
Sidebar Menu for MACos in Swiftui
How to Remove Node from Parent If Touched More Than Once
Type of Expression Is Ambiguous Without More Context in Xcode 11
Swiftui - Unwrap Optional Image Data to Create Image Based on Uiimage(Data)