2

I've put the following into a Playground to try and understand this and I just don't:

import Foundation

@objc protocol Sample {

    var value: Int { get set }

    func increase()
    func decrese()

}

extension Sample {

    func increase() {
        value += 1
    }

    func decrease() {
        value -= 1
    }

}

class Test: Sample {

    var value: Int = 0

}

The error appears next to the class declaration for Test saying:

Non-'@objc' method 'increase()' does not satisfy requirement of '@objc' protocol 'Sample'

If I re-declare increase() and decrease() in the class then the warning is silenced. Or also if I remove the declarations from the protocol. Could someone please explain?

EDIT

I do need an Objective-C class to conform to this protocol as well, hence the @objc at the start.

Mr.P
  • 1,390
  • 13
  • 35
  • You are providing default implementation for Swift scope only. As you protocol is `@objc` your `Test` class don't see default implementation – CZ54 Feb 10 '20 at 14:52
  • Since you used @-objc, when you implement a protocol, you need to implement its methods in the class you conform the protocol. Also you might want to use @objc optional for the methods you don't want to implement in the class. – Teja Nandamuri Feb 10 '20 at 14:52
  • Does this answer your question? [How to define optional methods in Swift protocol?](https://stackoverflow.com/questions/24032754/how-to-define-optional-methods-in-swift-protocol) – Teja Nandamuri Feb 10 '20 at 14:52

2 Answers2

5

The problem is that you’re defining these methods in a protocol extension. This is used to define a “default implementation” for a protocol (i.e. if a type doesn’t implement the method, the protocol’s implementation will be called).

But Objective-C doesn’t have the concept of default implementations for protocols. So it doesn’t makes sense to declare the protocol as @objc and have default implementations within the Swift protocol extension. An Objective-C class conforming to this protocol would never be able to enjoy these Swift default implementations.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Take a look https://stackoverflow.com/questions/39487168/non-objc-method-does-not-satisfy-optional-requirement-of-objc-protocol – Hayk Brsoyan Feb 24 '21 at 14:24
0

The below code works with empty protocol methods' implementation in the Protocol extension class

import Foundation

protocol Sample {
    var value: Int { get set }
    func increase()
    func decrease()
}

extension Sample {
    func increase() { }
    func decrease() { }
}

class Test: Sample {
    var value: Int = 0
}

or if you want some default implementation of Sample protocol methods in the extension then use

import Foundation

protocol Sample {
    var value: Int { get set }

    func increase()
    mutating func decrease()
}

extension Sample {
    func increase() {
        print("do anything")
    }

    mutating func decrease() {
        value -= 1
    }
}

class Test: Sample {
    var value: Int = 0
}

mutating is added before the protocol method decrease() because it modifies the Protocol variable value. If the Protocol extension doesn't modify any of the Protocol variable (e.g. increase()), then there is no need of mutating keyword

Noor
  • 967
  • 7
  • 18
  • It works no problem when the protocol isn't declared `@objc`, but as I stated, I need it to be accessible to ObjC. @Rob is right though. ObjC doesn't know anything about protocol extensions, hence the need to redeclare the implementations – Mr.P Sep 30 '21 at 13:01