How to require that a protocol can only be adopted by a specific class

SwiftGenericsProtocols

Swift Problem Overview


I want this protocol:

protocol AddsMoreCommands {
     /* ... */
}

only to be adopted by classes that inherit from the class UIViewController. This page tells me I can specify that it is only adopted by a class (as opposed to a struct) by writing

protocol AddsMoreCommands: class {
}

but I cannot see how to require that it is only adopted by a particular class. That page later talks about adding where clauses to protocol extensions to check conformance but I cannot see how to adapt that either.

extension AddsMoreCommands where /* what */ {
}

Is there a way to do this? Thanks!

Swift Solutions


Solution 1 - Swift

protocol AddsMoreCommands: class {
    // Code
}
    
extension AddsMoreCommands where Self: UIViewController {
    // Code
}

Solution 2 - Swift

This can also be achieved without an extension:

protocol AddsMoreCommands: UIViewController {
    // code
}

Which is exactly the same as:

protocol AddsMoreCommands where Self: UIViewController {
   // code
}

I usually use the first option, IIRC I read a while ago on the Swift docs that that is the recomended way when the constraint is Self, if is other constraint such as associate types is when where can be used.

Notice that since UIViewController is a class too, this protocol can be implemented for weak properties such as delegates.

EDITED 2021/01/05: Previous posted solution had a warning, I have removed it and use this one which does not produce any warning.

Solution 3 - Swift

Because of an issue in the previous answer I ended up with this declaration:

protocol AddsMoreCommands where Self : UIViewController { 
    // protocol stuff here  
}

no warnings in Xcode 9.1

Solution 4 - Swift

Now in Swift 5 you can achieve this by:

protocol AddsMoreCommands: UIViewController {
     /* ... */
}

Quite handy.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionemrys57View Question on Stackoverflow
Solution 1 - SwiftWitterquickView Answer on Stackoverflow
Solution 2 - SwiftrgkobashiView Answer on Stackoverflow
Solution 3 - SwiftMassmakerView Answer on Stackoverflow
Solution 4 - SwiftWojciech KulikView Answer on Stackoverflow