Swift - extending a class only when it conforms to a protocol to use method swizzling
<p>I have a protocol called <code>NakedNavigationBar</code>.</p>

<p>I also have an extension that extends all <code>UIViewController</code>s that conform to <code>NakedNavigationBar</code>.</p>

<p>The problem is that in the extension I want to add default behaviour so that when the <code>UIViewController</code> initialises, we use method swizzling on the <code>UIViewController</code>.</p>

<p>Here is my protocol and extension:</p>

<pre><code>import UIKit


protocol NakedNavigationBar
{

}

extension NakedNavigationBar where Self: UIViewController
{
    public override class func initialize()
    {
        struct Static
        {
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&amp;Static.token)
        {
            let originalSelector = #selector(viewWillAppear(_:))
            let swizzledSelector = #selector(nakedNavigationBar_viewWillAppear(_:))

            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

            let didAddMethod = class_addMethod(self,
                                               originalSelector,
                                               method_getImplementation(swizzledMethod),
                                               method_getTypeEncoding(swizzledMethod))

            if didAddMethod
            {
                class_replaceMethod(self,
                                    swizzledSelector,
                                    method_getImplementation(originalMethod),
                                    method_getTypeEncoding(originalMethod))
            }
            else
            {
                method_exchangeImplementations(originalMethod, swizzledMethod)
            }
        }
    }


    //  MARK: - Swizzling Methods

    func nakedNavigationBar_viewWillAppear(animated: Bool)
    {
        self.nakedNavigationBar_viewWillAppear(animated)

        print("VWA Swizzling...")

        //  Hide the navigation bar
        _setNavigationBarVisible(isVisible: false)
    }


    //  MARK: -

    private func _setNavigationBarVisible(isVisible isVisible: Bool)
    {
        // (Changes background and shadow image)
    }
}
</code></pre>

<p>The errors I get when building are:
<a href="https://i.stack.imgur.com/SckeG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/SckeG.png" alt="errors"></a></p>

<p>Essentially telling me that I cannot extend the protocol because it doesn’t have the <code>UIViewController</code> methods. But as I understand it, the <code>where Self: UIViewController</code> should make it so that this only works on a <code>UIViewController</code>, extending the view controller only when it conforms to <code>NakedNavigationBar</code>.</p>

<p>Originally the extension was <code>extension UIViewController: NakedNavigationBar</code> but this makes all of my <code>UIViewController</code>s instantly conform to <code>NakedNavigationBar</code> rather than only the ones I choose.</p>