2015-02-13 10 views
10

Ho appena aggiornato dal rapido 1.1 a rapida 1.2 e ottenere compilatore di errore:Swift 1.2 redeclares metodo Objective-C

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

Qui po 'di codice:

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

Ma ho bisogno di chiamare setVacation

Qualche suggerimento su come risolvere questo problema?

risposta

8

Ciò è causa di cambiamento indicato nel Xcode 6.3beta le note di rilascio:

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

Per risolvere questo problema è necessario fare tutti voi le firme dei metodi unici (come Objective-C non fornisce metodo di overload)

Oppure non ereditare da NSObject se hai bisogno solo della classe Swift.

+0

Questo sembra implicare che l'overloading dei metodi non è possibile in classi come UIViewControllers o, in effetti, qualsiasi classe che sottoclasse qualsiasi classe dell'obiettivo-c. È corretto? –

+0

Sembra che la soluzione alternativa sia dichiarare privati. In questo modo il compilatore non tenterà di convertirli in ObjC, quindi non ci sarà un conflitto. – kwerle

+0

@kwerle Soluzione eccezionale. Non ci avevo pensato prima. – Kirsteins

1

Come notato da @Kirsteins, Swift ora rileva i simboli in conflitto tra Swift e Obj-C e simboli rapidi che causerebbero il dolore Obj-C. In aggiunta alla risposta data, si può evitare questo, in generale, specificando un'etichetta necessaria per i tipi supplementari, cambiando così la firma di chiamata:

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) 

di là di questo, però, e per rispondere alla tua domanda immediata, si sta cercando per applicare gli idiomi Obj-C a Swift. Che cosa si vuole veramente, è o implementare didSet (più probabile), o, eventualmente, set:

class WhatIDidLastSummer { 

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

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

} 
+0

Ho un problema simile ma non è in un metodo setX. Sto facendo il compito dal corso Stanford Swift di iTunesU. Quando mi sono convertito a Swift 1.2, un codice che ha usato per compilare ha smesso di compilare. Il metodo è performOperation. –

+0

2 metodi con diverse firme. "func performOperation (operazione: (Double, Double) -> Double)", e: "func performOperation (operazione: (Double) -> Double)". Il primo non riceve un errore, ma il secondo lo fa. (L'errore è: "Metodo 'performOperation' ripristina il metodo Objective-C 'performOperation:'"). Potevo vedere "performOperation" essere un vero metodo ObjC da qualche parte ... ma allora perché il primo metodo non genera l'errore? –

+0

(Senza conoscere il tuo contesto), è perché quel particolare codice è derivato da NSObject, o contrassegnato come @objc, e Obj-C non supporta l'overloading di funzione/metodo, anche con differenti firme di tipo. TL; DR, funzionerà perfettamente in un ambiente solo Swift, ma Obj-C non può usarlo e il codice è derivato da Obj-C o reso disponibile a Obj-C. –

4

Cappy: Per il problema Standford ho usato semplicemente questo, perché sembra che l'Xcode Beta dice semplicemente che l'operazione: (Double, Double) -> Double è uguale all'operazione: Double -> Double, non so se è un bug o no ...

Ma il codice seguente funziona, ma è NON pulito :(

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