man.kar man.kar - 1 month ago 6
iOS Question

Inconsistency in Swift optional protocol behaviour

Coming from .Net, I am trying to learn Swift3/iOS and got puzzled by the following apparent inconsistent behaviour of optional protocol members. I suspect its something got to do with the juggling between objc/swift words, but what am I missing here actually?

// In playground, given below:

@objc protocol SomePtotocol {
@objc optional func someMethod()
}

class SomeDelegate: NSObject, SomePtotocol {
}

class SomeController: NSObject {
var delegate: SomePtotocol = SomeDelegate()
}

// This works and compiles without error

let controller = SomeController()
controller.delegate.someMethod?() // No error, typed as '(() -> ())?'

// But this fails to even compile ??

let delegate = SomeDelegate()
delegate.someMethod?() // Error: 'SomeDelegate' has no member 'someMethod'


I would expect either both to fail or both pass, so if someone could please enlighten me on this anomaly.

Answer

The difference between the two blocks of code is the type of the variable involved.

In the first block, delegate is explicitly typed as SomePtotocol, and this protocol defines the someMethod method, so your statement is valid.

In the second block, delegate is implicitly typed as SomeDelegate and although this class conforms to SomePtotocol, it doesn't implement the optional method someMethod, so you get an error.

If you change your second block to

let delegate: SomePtotocol = SomeDelegate()
delegate.someMethod?()

which is equivalent to the first block, then there is no error.