TL;DR -> scroll to bottom
In trying to tag Apple on the Protocol-Oriented Programming with Swift, I stumbled upon the following problem while trying to implement a delegation pattern between classes.
I'll start with this example:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: PhotoHandlerParent
}
So far, so good. An instance of MyViewController
would be happily assigned as PhotoHandler
's delegate. But say I not only wanted the delegate object to conform to PhotoHandlerParent
, but also be of class UIViewController
. In this particular example, so that the PhotoHandler
could present and dismiss an UIImagePickerController
on behalf of its parent view controller. Much like:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: UIViewController, PhotoHandlerParent
}
Unfortunetely, the code above doesn't work on Swift. On the other hand though, Swift does have Generics, that may help in this case. Thus one might try:
protocol PhotoHandlerParent {}
class UIViewController {}
class MyViewController: UIViewController, PhotoHandlerParent {}
class PhotoHandler<Parent where Parent: UIViewController, Parent: PhotoHandlerParent>: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: Parent
}
Now interestingly enough, an instance of MyViewController
would go back to be happily assigned as PhotoHandler
's delegate. No compile error, no runtime error. But...
TL;DR: The problem
Running the sample code for this question, it's possible to see that an instance of a class declared with Generics and set as a UIImagePickerController
's delegate is never called by it. An instance of an object declared without generics is called by the UIImagePickerController
.
My best assumption is that the compiler doesn't complain because it can verify that PhotoHandler
conforms to UIImagePickerControllerDelegate
. However, at runtime, the PhotoHandler
instance is actually a PhotoHandler<MyViewController>
instance, thus somehow interfering with the UIImagePickerController
's ability to identify that its delegate actually implements its protocol.
Or am I missing something maybe?
Cheers