With the transition from Swift 2 -> 3 I’ve started running into one particular 
issue VERY often (although it’s not necessarily specific to the transition). If 
a protocol method is optional (either because it is an @objc optional or 
because it has a default implementation) there is a risk that the conformer 
will have a misspelled or slightly incorrectly typed implementation of the 
method. For instance:

protocol RouteDestinationViewController: class {
        static func viewController(with url: URL, properties: [String:String]) 
-> UIViewController?
}

extension RouteDestinationViewController where Self: UIViewController {
        static func viewController(with url: URL, properties: [String:String]) 
-> UIViewController? {
                return Self.init()
        }
}

class FooController: UIViewController, RouteDestinationViewController {
        static func viewController(with url: URL, properties: [String:Any]) -> 
UIViewController? {
                return FooController(properties: properties)
        }
}

Notice the issue there? Properties is supposed to be [String:String], but 
FooController uses [String:Any] (this is an exact issue I ran into after a 
small refactor). When viewController(with:properties:) is called, it will use 
the default implementation instead of what the compiler sees as a completely 
different method. Over the betas the compiler has gotten better warnings about 
this, but is still not 100%.

Other cases of this issue are common with imported ObjC protocols that have 
different naming in Swift. In some cases an @objc name must be applied to 
ensure it is declared in a way that the protocol can see it.

We solve this problem with subclassing by requiring “override”. If the override 
keyword is present but the superclass doesn’t have a matching method, the 
compiler warns us about it. Similarly if the superclass implements the same 
method and the subclass doesn’t include override, we get a warning so that it 
is clear that you are overriding behavior.

For protocols, I don’t think a required keyword would be the best approach. 
It’s a completely valid case that a type could conform to a protocol using 
existing methods, perhaps even from a different module. Further, a single 
method could satisfy multiple protocols, and be overriden from a superclass. 
What I would propose would be something like an optional override(<#protocol 
name#>). Something like the following:

        override(RouteDestinationViewController) static func 
viewController(with url: URL, properties: [String:Any]) -> UIViewController? {
                return FooController(properties: properties)
        }

A method should be able to include multiple overrides (including a bare 
override to indicate that it is overriding a class method).

Thoughts? Are you seeing similar issues?

David Beck
http://davidbeck.co
http://twitter.com/davbeck
http://facebook.com/davbeck

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to