One explicit way to allow such operations in a type-safe manner is to introduce an “open existential” operation of some sort, which extracts and gives a name to the dynamic type stored inside an existential. For example:
if let storedInE1 = e1 openas T { // T is a the type of storedInE1, a copy of the value stored in e1
if let storedInE2 = e2 as? T { // is e2 also a T?
if storedInE1 == storedInE2 { … } // okay: storedInT1 and storedInE2 are both of type T, which we know is Equatable
}
}
If I'm not mistaken, this topic was in the "maybe" section, and I'd like to offer a concrete use case.
A while back I attempted to extend `UIStoryboard` to be a type-safe dependency injection container. For example, given a protocol like this:
protocol Presenter: class {
associatedtype Data // Don't worry too much about this name, it's probably overly generic
// Called by the dependency injection container after initialisation to inject the presented data.
func updateWithData(data: Data)
}
And then a view controller could declare itself to be a `Presenter`:
class ProfileViewController: Presenter {
typealias Data = Profile
private var profile: Profile?
func updateWithData(profile: Profile) {
self.profile = profile
updateDisplay()
}
}
And then when setting up your storyboard, you would register various factory closures to fetch this data on demand:
let storyboard = DIStoryboard(name: "Profile", registerDependencies: { dependencies in
dependencies.add { () -> Profile in
return profileCache.currentUserProfile
}
})
To glue these pieces together, you'd need a way to declare an existential type for the current view controller, and then match that against one of the registered factory functions:
// DIStoryboard.swift
private func updateViewController(viewController: UIViewController) {
if let <P: Presenter> presenter = viewController as? P {
// Now what? Possibly:
// 1. Iterate over each factory function
// 2. When I find a function () -> P.Data, call it and pass the result to viewController.updateWithData()
}
}
Is this a good idea, in general? I don't really know, because I couldn't really complete the experiment!
But I have a feeling that there might be other cases where opening existentials could allow for more type-safe code when wrapping UIKit functionality. Currently, Swift generics are completely incompatible with the way objects are unarchived from storyboards and nibs, and it feels like this feature _could_ help to bridge the gap. I have a feeling a lot of Swift users would like to bring more of Swift's type safety to their Cocoa code.
Anyway, I'd love to hear some feedback about this idea!
–Adam