2015-02-13 11 views
10

Właśnie aktualizowane od szybkiej 1,1 do szybkiej 1,2 i zdobyć kompilatora błąd:Swift 1.2 redeclares metoda Objective-C

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

Oto niektóre kodu:

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

Ale muszę zadzwonić setVacation

Czy są jakieś sugestie, jak to naprawić?

Odpowiedz

8

To jest przyczyna zmianą podanej w Xcode 6.3beta wydaniu:

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:’ 
} 

Do tego trzeba naprawić, aby wszyscy wy, metoda podpisów wyjątkowy (jak Objective-C nie daje przeciążenie metody)

Lub nie dziedzicz z NSObject, jeśli potrzebujesz tylko lekcji Swift.

+0

To pojawia się sugerować, że przeciążanie metod nie jest możliwe w takich klasach, jak UIViewControllers lub w istocie jakakolwiek klasa, która podklasuje dowolną klasę-c. Czy to jest poprawne? –

+0

Wygląda na to, że czystym rozwiązaniem jest zadeklarowanie tych prywatnych. W ten sposób kompilator nie będzie próbował przekonwertować ich na ObjC, więc nie będzie konfliktu. – kwerle

+0

@kwerle Niesamowite obejście. Nie myślałem o tym wcześniej. – Kirsteins

1

Jak zauważyli @Kirsteins, Swift wykrywa teraz sprzeczne symbole pomiędzy Swift i Obj-C oraz szybkie symbole, które spowodowałyby żałobę Obj-C. Oprócz odpowiedzi udzielonej można tego uniknąć w ogóle, określając wymaganą etykietę dodatkowych typów, zmieniając w ten sposób sygnaturę połączenia:

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) 

Poza tym, choć i odpowiedzieć na natychmiastowe pytanie, próbujesz zastosować idiomy Obj-C do Swifta. Co naprawdę chcesz, jest wdrożenie albo didSet (najbardziej prawdopodobne), albo ewentualnie set:

class WhatIDidLastSummer { 

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

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

} 
+0

Mam podobny problem, ale nie jest to metoda setX. Wykonuję zadanie z kursu iTunesU Stanford Swift. Po konwersji na Swift 1.2, kod, który był używany do kompilacji, przestał się kompilować. Metodą jest performOperation. –

+0

2 metody z różnymi podpisami. "func performOperation (operacja: (Double, Double) -> Double)", i: "func performOperation (operacja: (Double) -> Double)". Pierwszy nie otrzymuje błędu, ale drugi robi. (Błąd: "Metoda" performOperation "redeclares Objective-C method" performOperation: ""). Widziałem gdzieś "performOperation" jako prawdziwą metodę ObjC ... ale dlaczego pierwsza metoda nie odradza błędu? –

+0

(Bez znajomości kontekstu), dzieje się tak dlatego, że ten konkretny kod pochodzi albo z NSObject, albo oznaczony jako @objc, a Obj-C nie obsługuje przeciążania funkcji/metody, nawet z różnymi sygnaturami typów. TL; DR, będzie działać dobrze tylko w środowisku Swift-only, ale Obj-C nie może z niego korzystać, a kod pochodzi albo z Obj-C, albo jest udostępniany dla Obj-C. –

4

Cappy: Dla problemu Standford użyłem po prostu to, bo to wygląda jak Xcode Beta po prostu mówi, że operacja: (Double, Double) -> Double jest tym samym co operacja: Double -> Double, nie wiem, czy to błąd, czy nie ...

Ale poniższy kod działa, ale jest NOT czysty : (

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() 
    } 
} 
Powiązane problemy