427

Is it possible in Swift? If not then is there a workaround to do it?

Ky -
  • 30,724
  • 51
  • 192
  • 308
Selvin
  • 12,333
  • 17
  • 59
  • 80
  • In case future readers are looking for it, here is the discussion of [optional protocol requirements](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols#Optional-Protocol-Requirements) from [The Swift Programming Language](https://docs.swift.org/swift-book/documentation/the-swift-programming-language). – Rob Mar 22 '23 at 19:17

19 Answers19

647

1. Using default implementations (preferred).

protocol MyProtocol {
    func doSomething()
}

extension MyProtocol {
    func doSomething() {
        /* return a default value or just leave empty */
    }
}

struct MyStruct: MyProtocol {
    /* no compile error */
}

Advantages

  • No Objective-C runtime is involved (well, no explicitly at least). This means you can conform structs, enums and non-NSObject classes to it. Also, this means you can take advantage of powerful generics system.

  • You can always be sure that all requirements are met when encountering types that conform to such protocol. It's always either concrete implementation or default one. This is how "interfaces" or "contracts" behave in other languages.

Disadvantages

  • For non-Void requirements, you need to have a reasonable default value, which is not always possible. However, when you encounter this problem, it means that either such requirement should really have no default implementation, or that your you made a mistake during API design.

  • You can't distinguish between a default implementation and no implementation at all, at least without addressing that problem with special return values. Consider the following example:

    protocol SomeParserDelegate {
        func validate(value: Any) -> Bool
    }
    

    If you provide a default implementation which just returns true — it's fine at the first glance. Now, consider the following pseudo code:

    final class SomeParser {
        func parse(data: Data) -> [Any] {
            if /* delegate.validate(value:) is not implemented */ {
                /* parse very fast without validating */
            } else {
                /* parse and validate every value */
            }
        }
    }
    

    There's no way to implement such an optimization — you can't know if your delegate implements a method or not.

    Although there's a number of different ways to overcome this problem (using optional closures, different delegate objects for different operations to name a few), that example presents the problem clearly.


2. Using @objc optional.

@objc protocol MyProtocol {
    @objc optional func doSomething()
}

class MyClass: NSObject, MyProtocol {
    /* no compile error */
}

Advantages

  • No default implementation is needed. You just declare an optional method or a variable and you're ready to go.

Disadvantages

  • It severely limits your protocol's capabilities by requiring all conforming types to be Objective-C compatible. This means, only classes that inherit from NSObject can conform to such protocol. No structs, no enums, no associated types.

  • You must always check if an optional method is implemented by either optionally calling or checking if the conforming type implements it. This might introduce a lot of boilerplate if you're calling optional methods often.

akashivskyy
  • 44,342
  • 16
  • 106
  • 116
  • 2
    Because "optional requirement" (which is an oxymoron itself) goes against the idea of contract + prevents static dispatch. One of the Swift Core Team members (I don't remember who that was exactly) said that Swift only has "optional protocol requirements" because it is needed for Obj-C interop. Also, the idea of native "optional requirements" was quickly discarded in the early days of swift-evolution. – akashivskyy Apr 27 '17 at 09:00
416

In Swift 2 and onwards it's possible to add default implementations of a protocol. This creates a new way of optional methods in protocols.

protocol MyProtocol {
    func doSomethingNonOptionalMethod()
    func doSomethingOptionalMethod()
}

extension MyProtocol {
    func doSomethingOptionalMethod(){ 
        // leaving this empty 
    }
}

It's not a really nice way in creating optional protocol methods, but gives you the possibility to use structs in in protocol callbacks.

I wrote a small summary here: https://www.avanderlee.com/swift-2-0/optional-protocol-methods/

Antoine
  • 23,526
  • 11
  • 88
  • 94
  • 2
    This is probably the cleanest way to do it in Swift. Too bad it does not work prior to Swift 2.0. – Entalpi Sep 03 '15 at 08:32
  • 16
    @MattQuiros I'm finding that you do in fact need to declare the function in the protocol definition, otherwise the no-op extension function doesn't get overridden in your classes that conform to the protocol. – Ian Pearce Sep 30 '15 at 18:13
  • 5
    @IanPearce is correct, and this appears to be by design. In the "Protocol Oriented Programming" talk (408) at WWDC, they talk about methods in the main protocol being "customization points" offered to conforming types. A required point of customization doesn't receive a definition in an extension; an optional point does. Methods on the protocol that generally should not be customized are wholly declared/defined in the extension to disallow conforming types to customize *unless you specifically cast down to its dynamicType* to show you want the conformer's custom implementation. – matthias Oct 01 '15 at 09:54
  • 1
    Good writeup of the subtlety in dynamic dispatch to protocol or implementing class here: http://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future?utm_campaign=iOS%2BDev%2BWeekly&utm_medium=web&utm_source=iOS_Dev_Weekly_Issue_203 – farhadf Oct 05 '15 at 23:42
  • But in this way you can not check if the method is implemented or not (it always is, but empty). The delegate source in real life checks if the delegate implements the selector or not and then according to the result does different things. – Darko Apr 02 '16 at 07:50
  • @Darko, in that case I think you can enable the optional method to throw `MethodNotImplementedError` or something similar (as in Java). – Franklin Yu Jun 09 '16 at 21:18
  • 4
    @FranklinYu You can do this but then you are poluting your API design with 'throws' where it's in fact not needed. I like more the idea of "micro protocols". E.g. each method confirms to one protocol and then you can check for: if object is protocol – Darko Jun 09 '16 at 21:28
  • So in other words you provide its implementation in the extension through defaulting it. However since the implementation is empty, ie it has no code, you can *think* of it as an optional method? – mfaani Dec 16 '16 at 14:58
  • 5
    @Antoine I think you should make the function in the extension public, since the functions in the protocols are public by definition. Your solution will not work when the protocol will be used outside of its module. – Vadim Eisenberg Jan 23 '17 at 16:18
43

Here is a concrete example with the delegation pattern.

Setup your Protocol:

@objc protocol MyProtocol:class
{
    func requiredMethod()
    optional func optionalMethod()
}

class MyClass: NSObject
{
    weak var delegate:MyProtocol?

    func callDelegate()
    {
        delegate?.requiredMethod()
        delegate?.optionalMethod?()
    }
}

Set the delegate to a class and implement the Protocol. See that the optional method does not need to be implemented.

class AnotherClass: NSObject, MyProtocol
{
    init()
    {
        super.init()

        let myInstance = MyClass()
        myInstance.delegate = self
    }

    func requiredMethod()
    {
    }
}

One important thing is that the optional method is optional and needs a "?" when calling. Mention the second question mark.

delegate?.optionalMethod?()
Raphael
  • 3,846
  • 1
  • 28
  • 28
40

Since there are some answers about how to use optional modifier and @objc attribute to define optional requirement protocol, I will give a sample about how to use protocol extensions define optional protocol.

Below code is Swift 3.*.

/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {

    /// default implementation is empty.
    func cancel()
}

extension Cancelable {

    func cancel() {}
}

class Plane: Cancelable {
  //Since cancel() have default implementation, that is optional to class Plane
}

let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*

Please notice protocol extension methods can't invoked by Objective-C code, and worse is Swift team won't fix it. https://bugs.swift.org/browse/SR-492

Lukas
  • 3,423
  • 2
  • 14
  • 26
Eddie.Dou
  • 459
  • 4
  • 5
  • 1
    Good job! This should be the correct answer since it solves the problem without getting Objective-C runtime involved. – Lukas Jul 17 '17 at 08:37
  • from swift documentation - "Protocol requirements with default implementations provided by extensions are distinct from optional protocol requirements. Although conforming types don’t have to provide their own implementation of either, requirements with default implementations can be called without optional chaining." – Mec Os May 02 '19 at 00:18
36

The other answers here involving marking the protocol as "@objc" do not work when using swift-specific types.

struct Info {
    var height: Int
    var weight: Int
} 

@objc protocol Health {
    func isInfoHealthy(info: Info) -> Bool
} 
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"

In order to declare optional protocols that work well with swift, declare the functions as variables instead of func's.

protocol Health {
    var isInfoHealthy: (Info) -> (Bool)? { get set }
}

And then implement the protocol as follows

class Human: Health {
    var isInfoHealthy: (Info) -> (Bool)? = { info in
        if info.weight < 200 && info.height > 72 {
            return true
        }
        return false
    }
    //Or leave out the implementation and declare it as:  
    //var isInfoHealthy: (Info) -> (Bool)?
}

You can then use "?" to check whether or not the function has been implemented

func returnEntity() -> Health {
    return Human()
}

var anEntity: Health = returnEntity()

var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))? 
//"isHealthy" is true
Zag
  • 819
  • 1
  • 8
  • 12
  • 3
    With this solution you can't access self from within any of the protocol functions. This may cause issues in some cases! – George Green Aug 20 '14 at 00:12
  • 1
    @GeorgeGreen You can access self. Mark the function variable as lazy and use a [capture list inside the closure](https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_100). – Zag Aug 21 '14 at 22:41
  • Only classes, protocols, methods and properties can use @objc. In case you are using an Enum parameter in the @ objc protocol method defination, you are doomed. – khunshan Oct 31 '14 at 11:54
  • 1
    @khunshan, this method requires nothing being marked @ objc, what are you referring to? – Zag Aug 20 '15 at 13:29
  • its an information on the topic that enums cannot be used in between swift and objc which the for other statements can be bridged with @objc keyword. – khunshan Aug 21 '15 at 05:36
  • For the first error you mentionned, you need to make the protocol as a subclass of NSObject: `@objc protocol Health: AnyObject {...` – tontonCD May 17 '19 at 08:43
35

In Swift 3.0

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

It will save your time.

Gautam Sareriya
  • 1,833
  • 19
  • 30
29
  • You need to add optional keyword prior to each method.
  • Please note, however, that for this to work, your protocol must be marked with the @objc attribute.
  • This further implies that this protocol would be applicable to classes but not structures.
jackslash
  • 8,550
  • 45
  • 56
Mehul Parmar
  • 3,599
  • 3
  • 26
  • 42
17

There are two ways you can create optional method in swift protocol.

1 - The first option is to mark your protocol using the @objc attribute. While this means it can be adopted only by classes, it does mean you mark individual methods as being optional like this:

@objc protocol MyProtocol {
    @objc optional func optionalMethod()
}

2 - A swiftier way: This option is better. Write default implementations of the optional methods that do nothing, like this.

protocol MyProtocol {
    func optionalMethod()
    func notOptionalMethod()
}

extension MyProtocol {

    func optionalMethod() {
        //this is a empty implementation to allow this method to be optional
    }
}

Swift has a feature called extension that allow us to provide a default implementation for those methods that we want to be optional.

Himanshu
  • 287
  • 3
  • 9
14

A pure Swift approach with protocol inheritance:

//Required methods
protocol MyProtocol {
    func foo()
}

//Optional methods
protocol MyExtendedProtocol: MyProtocol {
    func bar()
}

class MyClass {
    var delegate: MyProtocol
    func myMethod() {
        (delegate as? MyExtendedProtocol).bar()
    }
}
guenis
  • 2,520
  • 2
  • 25
  • 37
11

To illustrate the mechanics of Antoine's answer:

protocol SomeProtocol {
    func aMethod()
}

extension SomeProtocol {
    func aMethod() {
        print("extensionImplementation")
    }
}

class protocolImplementingObject: SomeProtocol {

}

class protocolImplementingMethodOverridingObject: SomeProtocol {
    func aMethod() {
        print("classImplementation")
    }
}

let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()

noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"
eLillie
  • 653
  • 9
  • 17
8

I think that before asking how you can implement an optional protocol method, you should be asking why you should implement one.

If we think of swift protocols as an Interface in classic object oriented programming, optional methods do not make much sense, and perhaps a better solution would be to create default implementation, or separate the protocol into a set of protocols (perhaps with some inheritance relations between them) to represent the possible combination of methods in the protocol.

For further reading, see https://useyourloaf.com/blog/swift-optional-protocol-methods/, which gives an excellent overview on this matter.

emem
  • 5,588
  • 1
  • 24
  • 30
  • This. It's adherence to the ["I"](https://en.wikipedia.org/wiki/Interface_segregation_principle) principle in the [**SOLID** software development principles](https://en.wikipedia.org/wiki/SOLID). – Eric Jul 24 '18 at 10:43
7

Slightly off topic from the original question, but it builds off Antoine’s idea and I thought it might help someone.

You can also make computed properties optional for structs with protocol extensions.

You can make a property on the protocol optional

protocol SomeProtocol {
    var required: String { get }
    var optional: String? { get }
}

Implement the dummy computed property in the protocol extension

extension SomeProtocol {
    var optional: String? { return nil }
}

And now you can use structs that do or don’t have the optional property implemented

struct ConformsWithoutOptional {
    let required: String
}

struct ConformsWithOptional {
    let required: String
    let optional: String?
}

I’ve also written up how to do optional properties in Swift protocols on my blog, which I’ll keep updated in case things change through the Swift 2 releases.

matthewpalmer
  • 2,619
  • 3
  • 25
  • 27
5

How to create optional and required delegate methods.

@objc protocol InterViewDelegate:class {

    @objc optional func optfunc()  //    This is optional
    func requiredfunc()//     This is required 

}
Misha
  • 5,260
  • 6
  • 35
  • 63
Saurabh Sharma
  • 187
  • 2
  • 8
3

Here's a very simple example for swift Classes ONLY, and not for structures or enumerations. Note that the protocol method being optional, has two levels of optional chaining at play. Also the class adopting the protocol needs the @objc attribute in its declaration.

@objc protocol CollectionOfDataDelegate{
   optional func indexDidChange(index: Int)
}


@objc class RootView: CollectionOfDataDelegate{

    var data = CollectionOfData()

   init(){
      data.delegate = self
      data.indexIsNow()
   }

  func indexDidChange(index: Int) {
      println("The index is currently: \(index)")
  }

}

class CollectionOfData{
    var index : Int?
    weak var delegate : CollectionOfDataDelegate?

   func indexIsNow(){
      index = 23
      delegate?.indexDidChange?(index!)
    }

 }
Blessing Lopes
  • 570
  • 1
  • 5
  • 11
  • Can you describe a little more the "_two levels of optional at play_" part, namely this: `delegate?.indexDidChange?(index!)`? – Unheilig Mar 05 '15 at 20:40
  • 2
    If we had written the protocol to have a non optional method like this: `protocol CollectionOfDataDelegate{ func indexDidChange(index: Int) }` then you would call it without the question mark: `delegate?.indexDidChange(index!)` When you set a optional requirement for a method in a protocol, the Type that will conform to it might NOT implement that method, so the `?` is used to check for the implementation and If there is none the program will not crash. @Unheilig – Blessing Lopes Mar 06 '15 at 18:43
  • `weak var delegate : CollectionOfDataDelegate?` (ensure weak reference?) – Alfie Hanssen Jun 24 '15 at 17:05
  • @BlessingLopes Can you add your explanation of the `delegate?` usage to your answer? That information should really belong in there for others in the future. I want to upvote this, but that information should really be in the answer. – Johnathon Sullinger Jul 06 '15 at 19:29
3

if you want to do it in pure swift the best way is to provide a default implementation particullary if you return a Swift type like for example struct with Swift types

example :

struct magicDatas {
    var damagePoints : Int?
    var manaPoints : Int?
}

protocol magicCastDelegate {
    func castFire() -> magicDatas
    func castIce() -> magicDatas
}

extension magicCastDelegate {
    func castFire() -> magicDatas {
        return magicDatas()
    }

    func castIce() -> magicDatas {
        return magicDatas()
    }
}

then you can implement protocol without defines every func

p1ckl3
  • 177
  • 1
  • 4
0

One option is to store them as optional function variables:

struct MyAwesomeStruct {
    var myWonderfulFunction : Optional<(Int) -> Int> = nil
}

let squareCalculator =
    MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)
OwlOCR
  • 1,127
  • 11
  • 22
0

Let's understand the difference first

First example - If you write UITableViewDataSource then you need to write two method forcefully - That's the swift way default Protocol

Second Example - If you write UITableViewDelegate and aware that it doesn't show the red error that please add all the delegate method. It's up to you that which method you want to use. we can called as optional method!

Let's understand this by an example

First Swift Way default Protocol approach

class ContactModel{
    var firstname: String?
    var lastname: String?
}

protocol ContactDataSource: AnyObject{
    func contactConfiguration(contact: ContactModel)
}

class ViewController: ContactDataSource{
    func contactConfiguration(contact: ContactModel) {
        print(contact)
    }
}

Second approach - optional protocol

@objc
class UserModel: NSObject{
    var firstname: String = ""
}

@objc protocol UserDataSource{
    func contactConfiguration(user: UserModel)
   @objc optional func userInfo(user: UserModel)
}

class ViewController: UserDataSource{
    func contactConfiguration(user: UserModel) {
        print(user)
    }
}

Note: If you can see in optional protocal I haven't write userInfo method so its up to you. That mean With and without adding a method to the class its working fine. - called as a optional method in protocol

You must declare the class and protocol with the @objc attribute, and it's only working with Class not struct!

Third approach - optional protocol using Extension

Note: You can take Struct or Class

class UserModel{
    var firstname: String = ""
}

OR

struct UserModel{
    var firstname: String = ""
}

AND

protocol UserDataSource{
    func contactConfiguration(user: UserModel)
}

extension UserDataSource{
    func userInfo(user: UserModel){}
}

class myview: UserDataSource{
    func contactConfiguration(user: UserModel) {
        print(user)
    }
}
Yogesh Patel
  • 1,893
  • 1
  • 20
  • 55
-1

To define Optional Protocol in swift you should use @objc keyword before Protocol declaration and attribute/method declaration inside that protocol. Below is a sample of Optional Property of a protocol.

@objc protocol Protocol {

  @objc optional var name:String?

}

// Now if try to implement that protocol inside our code that will not force to include that function inside our class.

class MyClass: Protocol {

   // No error

}

Another way is to use protocol extension we can also give default implementation of that protocol. So that that functional of that protocol will make optional.

  • 2
    While this may answer the question it's better to add some description on how this answer may help to solve the issue. Please read [_How do I write a good answer_](https://stackoverflow.com/help/how-to-answer) to know more. – Roshana Pitigala Aug 03 '18 at 11:43
  • Hi @RoshanaPitigala i have edited my Answer. I have give proper explanation for how to make optional. – Ankur Gupta Jan 20 '23 at 12:05
-1

Define function in protocol and create extension for that protocol, then create empty implementation for function which you want to use as optional.

Rishu Gupta
  • 43
  • 1
  • 14