21

I want this function be in protocol:

func slideToRight(currentViewController viewController: UIViewController, completion: ((Bool)->())? = nil) {
    // do some stuff
}

But when I write such protocol:

protocol SomeDelegate { 
    func slideToRight(currentViewController viewController: UIViewController, completion: ((Bool)->())? = nil) 
}

I got an error:

Default argument not permitted in a protocol method

I know, I can define the signature in this way:

protocol SomeDelegate { 
    func slideToRight(currentViewController viewController: UIViewController, completion: ((Bool)->())?) 
}

But then, I won't be able to call the function missing "completion" word:

slideToRight(currentViewController viewController: vc)
pkamb
  • 33,281
  • 23
  • 160
  • 191
Roman Vygnich
  • 319
  • 1
  • 2
  • 6

1 Answers1

38

Unfortunately optional arguments are not allowed in protocols, but you can work around this by creating an extension of the protocol:

protocol SomeDelegate {
    // with the completion parameter
    func slideToRight(currentViewController viewController: UIViewController, completion: ((Bool)->())?)
}

extension SomeDelegate {
    // without the completion parameter
    func slideToRight(currentViewController viewController: UIViewController) {
        slideToRight(slideToRight(currentViewController: viewController, completion: nil))
    }
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • OP can add the default value when implementing the method. It is not allowed only in the protocol definition – Leo Dabus Mar 05 '18 at 16:27
  • 14
    @LeoDabus Yeah, but when you call the method on a protocol type, you still have to add the parameter. I think this is what the OP is trying to avoid. – Sweeper Mar 05 '18 at 16:28
  • You didn't get it `extension SomeDelegate { func slideToRight(currentViewController viewController: UIViewController, completion: ((Bool)->())? = nil) { // code } }` – Leo Dabus Mar 05 '18 at 16:29
  • 4
    @LeoDabus That kind of loses the point of the protocol doesn't it? You are not forced to implement method in that case. – Sweeper Mar 05 '18 at 16:31
  • This has nothing to do with the point of the protocol thats how OP needs to implement a default value. Btw it would be much better to extend UIViewController instead of passing it as a parameter `extension SomeDelegate where Self: UIViewController { func slideToRight(completion: ((Bool)->())? = nil) { } }` – Leo Dabus Mar 05 '18 at 16:33
  • `Unfortunately optional arguments are not allowed in protocols` ??? It is allowed and if you define it as optional you need to implement it as optional to conform to the protocol – Leo Dabus Mar 05 '18 at 16:51
  • @LeoDabus What do you mean by "???". According to here: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html "Default values, however, can’t be specified for method parameters within a protocol’s definition." – Sweeper Mar 05 '18 at 16:54
  • Talking about optional parameter. Btw No need to define a parameter as optional to set a default value other than nil – Leo Dabus Mar 05 '18 at 16:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/166262/discussion-between-sweeper-and-leo-dabus). – Sweeper Mar 05 '18 at 16:56
  • Great idea! Just changed my code, compiled and ran right away. – David H Mar 15 '19 at 21:14