2015-02-05 13 views
6

Ich arbeite mit einem Observer API (ObserverSet), die die folgende Funktion haben:swift - Teilfunktion Anwendung mit Generika

public func add<T: AnyObject>(object: T, _ f: T -> Parameters -> Void) -> ObserverSetEntry<Parameters> 

Es ist einfach ein object dann rufen Sie die Instanzmethode f auf dem object registrieren, wenn Benachrichtigung triggers

In einem meiner Manager, ich muss die vorherige Funktion mit einem von mir verstecken, so kann ich einen Beobachter zwingen, eine vordefinierte Funktion über ein Protokoll implementiert aufrufen.

Hier ist, was ich bisher getan habe:

@objc protocol Observer : NSObjectProtocol { 
    func observe(param: String) -> Void 
} 

func addObserver<T: AnyObject where T: Observer>(observer: T) { 
    let f: T -> String -> Void = observer.dynamicType.observe 
    entries.addObserver(observer, f) 
} 

Leider habe ich die folgende Fehlermeldung zeigt sich Partial application of generic method is not allowed,

ich eine mögliche Abhilfe irgendwo auf SO gefunden haben, die so aussehen:

let f: T -> String -> Void = { (obs: T) in obs.dynamicType.observe(obs) } 

Aber diese Codezeile treibt meine XCode verrückt mit einigen Segmentation Fault: 11 auf Kompilierung (und Communication interrupted mit Playground ..)

Gibt es eine Problemumgehung für das, was ich versuche zu tun?

+0

Was passiert, wenn Sie Ihr Protokoll als reines Swift-Protokoll deklarieren, anstatt es zu einem objc-Protokoll zu degradieren? – augustzf

+0

Genau der gleiche Fehler. Wenn ich auch die Implementierung von 'NSObjectProtocol' entferne, bekomme ich' error: 'T' ist kein Subtyp von 'inout T'' – Yaman

Antwort

4

habe ich nicht getestet, aber Sie können versuchen:

@objc protocol Observer : NSObjectProtocol { 
    func observe(param: String) -> Void 
} 

func addObserver<T: AnyObject where T: Observer>(observer: T) { 
    let f: T -> String -> Void = { ($0 as AnyObject).observe } 
    entries.addObserver(observer, f) 
} 

Zumindest diese kompiliert, weil AnyObject alle Methoden von ObjC hat - einschließlich @objc - Klassen/Protokolle, wie ImplicitlyUnwrappedOptional.

Also, das kompiliert:

let str = NSString(string: "test") 
(str as AnyObject).observe("foo") 

Natürlich führt dies zu Laufzeitfehler, da NSString keine observe(_:) Methode hat. Aber in Ihrem Fall ist T garantiert Observer, es sollte funktionieren.

+0

Yay! Diese Besetzung hat es getan. Aber ich verstehe nicht, warum ich einen Segmentierungsfehler ohne es habe? '' schon sagt, dass 'T' ein' AnyObject' ist, richtig? Möglicher Fehler? – Yaman

+0

Segface-Konflikt selbst ist definitiv ein Fehler. Aber ich bin mir nicht sicher über die Anforderung von Casting, es ist vielleicht eine Sprachbeschränkung. Wenn dies der Fall ist, sollte der Compiler eine entsprechende Fehlermeldung melden. – rintaro