100

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!

0

4 Answers 4

122
protocol AddsMoreCommands: class {
    // Code
}

extension AddsMoreCommands where Self: UIViewController {
    // Code
}
7
  • 4
    I so nearly had it... I wrote self instead of Self :-( Thank you very much, that works fine!
    – emrys57
    Commented Feb 1, 2016 at 16:03
  • For me, this causes some syntactic strangeness when I use this in conjunction with casting. Commented Aug 3, 2017 at 18:29
  • 3
    This won't work if you need to include a property in the protocol, as extensions cannot contain stored properties.
    – shim
    Commented Jan 12, 2018 at 19:15
  • 1
    It can have stored propertied you only need to use this: objc_getAssociatedObject(self, &KeyName) as? PropertyType Commented Apr 23, 2018 at 10:25
  • 1
    The docs changed to using AnyObject instead of class -> docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID281. But both versions are behaving the same for now without deprecation warnings.
    – heyfrank
    Commented Jul 12, 2018 at 13:43
92

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.

11
  • 6
    How coincidental is it that I clicked on a two year old question and find a perfect solution posted one hour ago 😲 Commented Oct 26, 2017 at 9:30
  • Xcode 9.1 is now giving me a warning about this saying: Redundant layout constraint 'Self' : 'AnyObject'. Layout constraint constraint 'Self' : 'AnyObject' implied here. Changing my code to the format of the accepted answer seems to be more gooder.
    – Zig
    Commented Nov 1, 2017 at 19:34
  • 3
    As of Xcode 9.1 class-only protocols now use AnyObject instead of class. protocol AddsMoreCommands: AnyObject where Self: UIViewController { // code }
    – dodgio
    Commented Nov 7, 2017 at 0:47
  • @dodgio still getting same warning using AnyObject
    – rgkobashi
    Commented Nov 7, 2017 at 0:59
  • 1
    @DávidPásztor you are right, however if you want to use it on a structural pattern such as delegation, to be able to make the property weak it is necessary to add ´class´ explicitly :)
    – rgkobashi
    Commented May 31, 2018 at 13:16
51

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

3
  • 5
    Correct me if I'm wrong, but the issue with this over the solution above (which is generating a warning in Xcode 9.1 and upwards), is that you can't declare the delegate as weak? Commented Apr 3, 2018 at 10:08
  • Also, when I use this solution with Swift 4.1, I need to cast properties of the AddsMoreCommands to UIViewController which I wanted to avoid...
    – heyfrank
    Commented Jul 12, 2018 at 13:48
  • 9
    To avoid the type cast, you could do this: typealias AddsMoreCommandsViewController = UIViewController & AddsMoreCommands
    – plu
    Commented Jul 21, 2018 at 20:00
39

Now in Swift 5 you can achieve this by:

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

Quite handy.

2
  • What is the difference between these two? extension AddsMoreCommands where Self: UIViewController { // Code } AND protocol AddsMoreCommands: UIViewController { /* ... */ } Thank you in advanced. Commented Dec 17, 2020 at 16:29
  • I think you meant protocol instead of extension, if that is the case, someone already answered it
    – rgkobashi
    Commented Feb 16, 2021 at 6:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.