'How to define optional methods in Swift protocol?

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



Solution 1:[1]

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/

Solution 2:[2]

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?()

Solution 3:[3]

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

Solution 4:[4]

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

Solution 5:[5]

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.

Solution 6:[6]

  • 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.

Solution 7:[7]

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()
    }
}

Solution 8:[8]

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"

Solution 9:[9]

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.

Solution 10:[10]

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.

Solution 11:[11]

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.

Solution 12:[12]

How to create optional and required delegate methods.

@objc protocol InterViewDelegate:class {

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

}

Solution 13:[13]

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!)
    }

 }

Solution 14:[14]

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

Solution 15:[15]

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)

Solution 16:[16]

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)
    }
}

Solution 17:[17]

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

Solution 18:[18]

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?

}

class MyClass: Protocol {

   // No error

}