2016-10-03 5 views
2

Ich habe eine Verlängerung, die nach oben,Swift 3 benötigt mehr Informationen, um einen Parameter abzuleiten?

aber in Swift 3,

Rischer Parameter 'T' konnte nicht geschlossen werden

public extension UIResponder 
    { 
    public func next<T>() -> T? 
     { 
     guard let responder = self.next 
      else { return nil } 
     return (responder as? T) ?? responder.next() 
     } 
    } 

// note - kudos to this excellent post: 
// https://blog.veloxdb.com/2016/05/12/bubbling-events-using-uiresponder-in-swift/ 

in Swift < 3, Sie blasen konnte Verwenden Sie das wie folgt:

class SnapDot:UIView 
    { 
    ..... 
    func handleTap(g:UITapGestureRecognizer) 
     { 
     (next() as Snap?)?.oneDotWasClicked(self) 
     } 

Ich habe Angst, dass ich nicht nur (a) nicht sehen kann, warum es nicht in Swift 3 gefolgert werden würde, sondern (b) sogar durch endlose Versuche zufälliger Variationen, kann ich es in Swift 3 nicht zum Laufen bringen: O

Antwort

3

Das ist eine Namenskollision zwischen der vorhandenen next Methode von UIResponder und Ihrer Erweiterungsmethode. self.next innerhalb Ihre Methode bezieht sich auf die (generische) Methode selbst.

die Erweiterung umbenennen macht es kompiliert:

public extension UIResponder { 
    public func nextOfType<T>() -> T? { 
     guard let responder = self.next 
      else { return nil } 
     return (responder as? T) ?? responder.nextOfType() 
    } 
} 

Und selbst wenn Sie nicht für sich fragen, hier ist ein iterative statt rekursive Version :)

public extension UIResponder { 
    public func nextOfType<T>() -> T? { 
     var current = self 
     while let responder = current.next { 
      if let match = responder as? T { 
       return match 
      } 
      current = responder 
     } 
     return nil 
    } 
} 
+0

Was ist * wirklich * komisch ist, dass das Hinzufügen eines unbenannten Arguments zur Funktion funktioniert, zB 'public func next (_: Void =()) -> T?'. Es scheint, dass der Compiler nicht in der Lage ist, zwischen Eigenschaften und argumentlosen Methoden mit denselben Namen zu disambiguieren (ich sehe nicht, warum Sie nicht in der Lage sein sollten, durch Casting oder durch Inferenz in diesem Fall zu disambiguieren) – Hamish

+0

@Hamish : Sie haben Recht, sowohl eine berechnete Eigenschaft 'var foo' als auch eine Methode' func foo() -> Int 'mit" ungültiger Deklaration "sowohl in Swift 2 als auch in 3 zu deklarieren. –

+0

Ich muss zugeben, meine andere knifflige Erweiterung, was ihr reparieren müsst ... http://stackoverflow.com/questions/39835397 ... Ich bin verwirrt, warum ich den Metatyp hier nicht benutzen muss. (Oder könnte das tatsächlich mit einem Metatyp-Ansatz geschrieben werden? Im Gegensatz zum 'if let'?) – Fattie

Verwandte Themen