19

I have a generic method in one of my classes where I want to have a generic type conforming to UIViewController and UIPickerViewDelegate. How can I do that? I thought of doing this:

func foo<T: UIViewController, UIPickerViewDelegate> (#viewController: T) {}

But this code doesn't "recognize" the UIPickerViewDelegate. I also thought of using the pipe | instead of the comma but this is even worse, the compiler doesn't accept that. Is it possible to do this or do I have to do 2 parameters for the class and the protocol? Or is there a nicer workaround?

Thanks for your help and Merry Christmas :]

borchero
  • 5,562
  • 8
  • 46
  • 72

3 Answers3

27

Your code:

func foo<T: UIViewController, UIPickerViewDelegate> (#viewController: T) {}

declares 2 generics parameters:

  • T which is UIViewController. And it's used as viewController parameter type.
  • UIPickerViewDelegate which is Any. And it's not used.

Instead, you should use "Where Clause", like:

func foo<T: UIViewController where T:UIPickerViewDelegate> (#viewController: T) {}
rintaro
  • 51,423
  • 14
  • 131
  • 139
  • Thank you very much! I didn't know the keyword `where` can be used there. But now I have another problem when calling this method in my viewController (conforming to UIPickerViewDelegate) by `.foo(viewController: self)` I get the following error: `Type 'UIViewController' does not conform to protocol 'UIPickerViewDelegate'`. What's the problem? Thanks for any help again ;) – borchero Dec 24 '14 at 11:32
  • `class MyViewController: UIViewController, UIPickerViewDelegate {... }` works for me. How do you declare the viewController? – rintaro Dec 24 '14 at 11:41
  • I have some other protocols, too: `UITableViewDataSource`, `UITableViewDelegate`, `UIPickerViewDataSource` – borchero Dec 24 '14 at 11:55
  • Thanks for this @rintaro! – Tomasz Szulc Jun 25 '15 at 19:25
  • @borchero Did you find a solution to this? I'm getting the same error, for some reason – mylogon May 01 '19 at 09:44
17

Since Swift 4 you can use the power of Protocol Composition. Here you go:

func foo<T: UIViewController & UIPickerViewDelegate> (viewController: T) {}
BilalReffas
  • 8,132
  • 4
  • 50
  • 71
11

Things have been changed in Swift 4: func foo<T: UIViewController> (viewController: T) where T:UIPickerViewDelegate {}

Vlad Papko
  • 13,184
  • 4
  • 41
  • 57