10

I just updated from swift 1.1 to swift 1.2 and get compiler Error:

Method 'setVacation' redeclares Objective-C method 'setVacation:'

Here some code:

var vacation : Vacation?  
func setVacation(_vacation : Vacation)
{...}

But I need call setVacation

Is any suggestions how fix this?

Braiam
  • 1
  • 11
  • 47
  • 78
UnRewa
  • 2,462
  • 2
  • 29
  • 31

3 Answers3

8

This is cause by the change stated in Xcode 6.3beta release notes:

Swift now detects discrepancies between overloading and overriding in the Swift type system and the effective behavior seen via the Objective-C runtime. (18391046, 18383574) For example, the following conflict between the Objective-C setter for “property” in a class and the method “setProperty” in its extension is now diagnosed:

 class A : NSObject {
     var property: String = "Hello" // note: Objective-C method 'setProperty:’
                                    // previously declared by setter for
                                    // 'property’ here
 }
 extension A {
     func setProperty(str: String) { } // error: method ‘setProperty’
                                       // redeclares Objective-C method
                                       //'setProperty:’
 }

To fix this you need to make all you method signatures unique (as Objective-C does not provide method overload)

Or don't inherit from NSObject if you need Swift only class.

Kirsteins
  • 27,065
  • 8
  • 76
  • 78
  • This appears to imply that method overloading is not possible in such classes as UIViewControllers or indeed any class that subclasses any objective-c class. Is that correct? – Vince O'Sullivan Feb 17 '15 at 19:51
  • It looks like the clean workaround is to declare these private. That way the compiler won't try to convert them to ObjC so there won't be a conflict. – kwerle Apr 21 '15 at 07:11
  • @kwerle Awesome workaround. Didn't think of this before. – Kirsteins Apr 22 '15 at 07:17
4

Cappy: For the Standford problem I used simply this, because it looks like the Xcode Beta simply says that the operation: (Double, Double) -> Double is the same as operation: Double -> Double, I don't know if it is a bug or not...

But the code below works, but is NOT clean :(

func performOperation(r:String? = "2", 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()
    }
}
Petr Šourek
  • 199
  • 6
1

As noted by @Kirsteins, Swift now detects conflicting symbols between Swift and Obj-C, and swift symbols that would cause Obj-C grief. In addition to the answer given, you can avoid this in general by specifying a required label for the additional types, thus changing the call signature:

import Foundation

extension NSObject {
    func foo(d:Double, i:Int) { println("\(d), \(i)") }
    func foo(withInt d:Int, i:Int) { println("\(d), \(i)") }
}

let no = NSObject()
no.foo(withInt:1, i: 2)

Beyond that though, and to answer your immediate question, you are trying to apply Obj-C idioms to Swift. What you really want, is to either implement didSet (most likely), or possibly set:

class WhatIDidLastSummer {

    var vacation:Bool = false {
        didSet {
            // do something
        }
    }

    var staycation:Bool {
        get { return true }
        set {
            // do something
        }
    }

}
Chris Conover
  • 8,889
  • 5
  • 52
  • 68
  • I have a similar problem but it's not in a setX method. I'm doing the assignment from the iTunesU Stanford Swift course. When I converted to Swift 1.2, some code that used to compile stopped compiling. The method is performOperation. – The Cappy Feb 21 '15 at 22:08
  • 2 methods with different signatures. "func performOperation(operation: (Double, Double)->Double )", and: "func performOperation(operation: (Double)->Double )". The first does not get an error, but the second one does. (The error is: "Method 'performOperation' redeclares Objective-C method 'performOperation:' "). I could see "performOperation" being a genuine ObjC method somewhere... but then why doesn't the first method spawn the error? – The Cappy Feb 21 '15 at 22:15
  • (Without knowing your context), it is because that particular code is either derived from NSObject, or marked as @objc, and Obj-C does not support function / method overloading, even with different type signatures. TL;DR, it will work just fine in a Swift-only environment, but Obj-C can't use it, and the code is either derived from Obj-C, or made available to Obj-C. – Chris Conover Feb 22 '15 at 01:04
  • Specifying a required label for the additional types: Great easy fix. Just add a # sign in front of the argument name to the method that begins with the name "set." e.g. func setCustomerList(#incomingList: CustomerList) – stone Apr 09 '15 at 07:16