Overloaded functions in swift error [duplicate] - ios

This question already has answers here:
Compiler error: Method with Objective-C selector conflicts with previous declaration with the same Objective-C selector
(6 answers)
Closed 7 years ago.
I am new to swift and have an error in the following code. I have one function with two different parameters. Xcode(version 6) is giving an error on the second definition with a parameter as a function which takes one value.Here is the code:
func performOperation(operation: (Double, Double) -> Double) {
if(operandStack.count >= 2){
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}
func performOperation(operation: Double -> Double){
if(operandStack.count >= 1){
displayValue = operation(operandStack.removeLast())
enter()
}
}

Update:
Another solution is add private before method definition (Source):
private func performOperation(operation: (Double, Double) -> Double) {
if(operandStack.count >= 2){
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}
private func performOperation(operation: Double -> Double){
if(operandStack.count >= 1){
displayValue = operation(operandStack.removeLast())
enter()
}
}
Original Answer:
Looks like your methods are defined in class that is inherited from some Objective-C class, for example:
class TestClass : NSObject {
func test(a : String) {}
func test(a : UInt) {}
}
Compiler will produce such error:
Method 'test' with Objective-C selector 'test:' conflicts with
previous declaration with the same Objective-C selector.
To fix that you need avoid inheritance from Objective-C class:
class TestClass {
func test(a : String) {}
func test(a : UInt) {}
}
This variant will work correct.
The problem is that Objective-C doesn't support methods overloading, but Swift does. That's why you need create pure Swift class.

Related

Non-'#objc' method does not satisfy requirement of '#objc' protocol [duplicate]

This question already has answers here:
Non-'#objc' method does not satisfy optional requirement of '#objc' protocol
(3 answers)
Closed 1 year ago.
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.
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.
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

Swift 3.0 Extension - Methods are not getting called in Child class

I have an Extension implementation problem when I am converting my code from swift 2.3 to swift 3.0.
Problem statement: -
1) Each inherited class asking for protocol implementation
2) Not able to call methods which are already implemented in Extension.
Please check below code for more understanding.
protocol MyExtension {
static func addTwoNumber(number1: Double, number2: Double)
}
extension MyExtension {
static func addTwoNumber(number1: Double, number2: Double) {
//implementation
}
static func subTractTwoNumbers(number1: Double, number2: Double) {
//implementation
}
}
internal class firstClass: MyExtension {
static func multiplyTwoNumbers(number1: Double, number2: Double) {
//implementation
// if I call subTractTwoNumbers in this class it is giving me an error
subTractTwoNumbers(10, 10)
//and asking me to implement protocol method as well ie
//static func addTwoNumber(number1: Double, number2: Double)
}
}
Please let me know, what I am doing wrong.
Replace this
subTractTwoNumbers(10, 10)
With
subTractTwoNumbers(number1: 10, number2: 10) // you must have to pass the argument lables name to call the function.
If you don’t want an argument label for a parameter, write an underscore (_) instead of an explicit argument label for that parameter
static func subTractTwoNumbers(_: Double, _: Double) {
//implementation
}
Also, you have written one extra curly braces at the end.
Write function in extension as below
extension MyExtension {
func addTwoNumber(number1: Double, number2: Double) {
//implementation
}
func subTractTwoNumbers(number1: Double, number2: Double) {
//implementation
}
}

Why delegate.respondsToSelector (Selector ("testEnum:")) this code will return false in swift language?

I was a few days ago from Objective-C to write Swift language, in the project I have encountered a problem.This problem is when using respondsToSelector ("testEnum:") function to check whether to implement the function of the testEnum:,if the param is the case, it will return false, I have tried other types, it will return true, do not know what is the reason, see the following code, to help me solve it, thank you very much!
enum TestEnum {
case A
case B
case C
}
protocol TestAProtocol: NSObjectProtocol {
func testEnum(testEnum: TestEnum);
func testInt(testInt: Int);
}
class TestA: NSObject {
var delegate: TestAProtocol?;
func executeDelegateCallBack() {
if (delegate != nil && delegate!.respondsToSelector(Selector("testEnum:"))) { // delegate!.respondsToSelector(Selector("testEnum:")) return false ?
delegate?.testEnum(TestEnum.A);
}
if (delegate != nil && delegate!.respondsToSelector(Selector("testInt:"))) { // delegate!.respondsToSelector(Selector("testInt:")) return true ?
delegate?.testInt(0);
}
}
}
class TestB: NSObject, TestAProtocol {
func initTestB () {
let testA: TestA = TestA();
testA.delegate = self;
testA.executeDelegateCallBack();
}
// mark TestAProtocol
func testInt(testInt: Int) {
}
func testEnum(testEnum: TestEnum) {
}
}
respondsToSelector() uses the Objective-C runtime and works only with
methods which are Objective-C compatible. Swift enums can only be
represented in Objective-C if they are marked with #objc, and that
requires that they have an integer raw value.
So with
#objc enum TestEnum : Int {
case A
case B
case C
}
your respondsToSelector(Selector("testEnum:") will return true.
Note however that testing for the presence of a method makes only
sense with optional protocol methods, and these are only available
for #objc protocols, for example:
#objc enum TestEnum : Int {
case A
case B
case C
}
#objc protocol TestAProtocol: NSObjectProtocol {
optional func testEnum(testEnum: TestEnum)
func testInt(testInt: Int)
}
And then it is much simpler to use optional chaining instead of
respondsToSelector:
func executeDelegateCallBack() {
delegate?.testEnum?(.A)
// ...
}
or more detailed:
func executeDelegateCallBack() {
if let testEnum = delegate?.testEnum {
testEnum(.A)
} else {
print("delegate is `nil` or does not respond to `testEnum`")
}
// ...
}

Returning Generic.Type for later use with class methods

Is it possible to return a type of generic that conforms to protocol for later use with class functions using Swift 1.2? Take a look:
protocol SomeProtocol
{
static func start(kind: Kind)
}
class A: SomeProtocol
{
class func start(kind: Kind)
{
print("A started")
}
}
class B: SomeProtocol
{
class func start(kind: Kind)
{
print("B started")
}
}
enum Kind {
case Akind
case Bkind
private func classKind<T: SomeProtocol>() -> T.Type
{
switch self {
case .Akind: return A.self
case .Bkind: return B.self
}
}
func doSomething() {
self.classKind().start(self)
}
}
I tried various methods but every of them ended with some errors. Currently I got 'A' is not a subtype of 'T' in classKind method (same for 'B') and cannot invoke 'start' with an argument list of type '(Kind)' in doSomething.
I'm sure I'm pretty close but can't solve it...
If you're using Swift 2, to achieve what you want you only need to change:
private func classKind<T: SomeProtocol>() -> T.Type { ... }
to
private func classKind() -> SomeProtocol.Type { ... }
Now back to the not-working code to see where the errors were coming from. You don't need to make the changes I'm now detailing, this is just to explain the errors.
First examine your doSomething method:
func doSomething() {
self.classKind().start(self)
// Error: Argument for generic parameter 'T' could not be inferred.
//
// (I'm using Xcode 7 b6, which may explain the differing error messages)
}
For the type returned by classKind to be inferred, you'd have to do:
let type: A.Type = self.classKind() // Or you could use `B.Type`.
type.start(self)
Which obviously defeats the point of your goal, since you have to specify the type you want.
Secondly, the errors in classKind:
private func classKind<T: SomeProtocol>() -> T.Type
{
switch self {
case .Akind: return A.self
// Cannot convert return expression of type 'A.Type' to return type 'T.Type'.
case .Bkind: return B.self
// Cannot convert return expression of type 'B.Type' to return type 'T.Type'.
}
}
To see why this doesn't work consider the following example, in which I have another type that conforms to SomeProtocol:
struct C: SomeProtocol { ... }
Then in doSomething:
func doSomething() {
let type: C.Type = self.classKind()
type.start(self)
}
The errors you're getting can now be read as: Cannot convert return expression of type 'A.Type'/'B.Type' to return type 'C.Type'.

Swift: type must implement protocol and be a subclass of given class [duplicate]

This question already has answers here:
Swift: Property conforming to a specific class and in the same time to multiple protocols
(3 answers)
Closed 8 years ago.
In Objective-C, you could define a type as being of a given class and implementing a protocol:
- (UIView <Protocol> *)someMethod;
This would tell that the value returned by someMethod was a UIView implementing a given protocol Protocol. Is there a way to enforce something similar in Swift?
You can do it like this:
protocol SomeProtocol {
func someMethodInSomeProtocol()
}
class SomeType { }
class SomeOtherType: SomeType, SomeProtocol {
func someMethodInSomeProtocol() { }
}
class SomeOtherOtherType: SomeType, SomeProtocol {
func someMethodInSomeProtocol() { }
}
func someMethod<T: SomeType where T: SomeProtocol>(condition: Bool) -> T {
var someVar : T
if (condition) {
someVar = SomeOtherType() as T
}
else {
someVar = SomeOtherOtherType() as T
}
someVar.someMethodInSomeProtocol()
return someVar as T
}
This defines a function that returns an object of type 'SomeType' and protocol 'SomeProtocol' and returns an object that adheres to those conditions.

Resources