Is it possible in Swift to create a generic constraint on sub-properties of the argument? For example, in this contrived example I have:
protocol LifecycleEmitting: UIView { ... }
protocol Viewing {
var view: UIView { get }
}
protocol Emedding {
var view: Viewing { get }
}
And I want to create an embed function that only operates on views that conforms to LifecycleEmitting. Today, I have to use runtime checks and crash or return:
Your protocol has a member view of concrete type Viewing, which is an existential type. This is why you can't spell what you want to do:
func embed<T: Emedding where T.view: LifecycleEmitting>(embedder: T) {
^~~~ You need to name a type, but this isn't one
Of course, there's no sense in trying to write where T.Viewing: LifecycleEmitting, because Viewing is a concrete type that doesn't conform to LifecycleEmitting. What you want instead is an associated type:
protocol Embedding {
associatedtype View
var view: View { get }
}
Then you can write:
func embed<T: Embedding>(embedder: T) where T.View: LifecycleEmitting { ... }
to preserve the requirements of Embedding, right? Hmm, unfortunately just updating Emedding to use an associated type with a Viewing constraint isn't passing the compiler in other places that conformed to it, investigating.
I assumed there were some errors in the original question in simplifying a larger design for the purpose of asking the question. I don't think you mean to have an associated type constrained to both LifecycleEmitting (to which some UIView classes conform) and Viewing (which contains a UIView instance).