2015-09-18 8 views
7

Ich habe versucht, CQRS-Muster in der schnellen iOS-App zu implementieren, und ich fand seltsames Verhalten.Swift - Generika Problem Ursache Speicherverlust

Klassen Kern:

class Query<T> {} 

class QueryHandler<TResult, TQuery:Query<TResult>> { 

    func execute(query: TQuery, callback: (result: TResult) -> Void) { 
    } 
} 

Implementierung von Klassen:

class GetRandomStringsQuery: Query<[String]> { 
internal var prefix:String 

init(prefix: String) { 
    self.prefix = prefix 
    } 
} 

class GetRandomStringsQueryHandler: QueryHandler<[String], GetRandomStringsQuery> { 

    override func execute(query: GetRandomStringsQuery, callback: (result: [String]) -> Void) { 
     var result = [String]() 

     for var i = 0; i < 100; i++ { 
      result.append("[\(i)]: \(query.prefix)") 
     } 

     callback(result: result) 
    } 
} 

Beispiel Nutzung:

@IBAction func generateMemoryLeak(sender: AnyObject) { 
     let query = GetRandomStringsQuery(prefix: "leak leak leak :(") 

     let queryHandler = GetRandomStringsQueryHandler() 

     queryHandler.execute(query) { (result) -> Void in 
      print("total records: \(result.count)") 
     } 
} 

In Rückruf sollten wir 100 Elemente in Array erhalten. Zur Laufzeit scheint die Referenz verloren gegangen zu sein und der Wert ist unbekannt. iOS Developer Instruments erkennt Speicherlecks.

Weid Behavior ist, dass, wenn wir Super-Klasse von GetRandomStringsQueryHandler entfernen und "Override" Modifier von der Funktion ausführen, wird es kein Speicherleck und App wird gut funktionieren!

Kann jemand dieses Verhalten erklären? Es ist mein Fehler oder schnelles Problem?

Ich verwende letzte verion von Xcode mit schnellen 2.

+0

Wie Sie bestimmen, ein Speicherleck gibt es? Laufen Sie auf einem echten Gerät mit wenig Speicher und einem Absturz? Oder nur mit Instrumenten bestätigen? Und wenn Sie in Instrumenten bestätigen, verwenden Sie ein echtes Gerät oder einen Simulator? Und welche Art von Speicher wird als undicht gemeldet? – nhgrif

+0

Gerade jetzt, wenn ich die App ausführen, erhalte ich die Ausnahme: EXC_BAD_ACCESS in libswiftCore.dylib'_swift_release_ (swift :: HeapObject *): In Verbindung mit Gerät verwende ich Simulator. – razor118

+0

Das ist ein bisschen anders als ein Speicherleck und sollte wahrscheinlich zu Ihrer Frage hinzugefügt werden. – nhgrif

Antwort

2

Interessante Frage! Ich habe Ihren Code auf den Spielplatz geklebt und den Fehler, den Sie festgestellt haben, reproduziert. Ich habe versucht, den Code zu optimieren, konnte aber die Generika nicht zum Laufen bringen. Als Alternative schreibe ich den Code mithilfe von Protokollen neu, um die Einschränkungen auszudrücken.

Kernprotokolle:

protocol QueryType { 
    typealias ResultType 
} 

protocol QueryHandler { 
    typealias Query: QueryType 
    func execute(query: Self.Query, callback: (result: Self.Query.ResultType) -> Void) 
} 

Konforme Klassen:

class GetRandomStringsQuery: QueryType { 
    typealias ResultType = [String] 

    internal var prefix:String 

    init(prefix: String) { 
     self.prefix = prefix 
    } 
} 


class GetRandomStringsQueryHandler: QueryHandler { 

    func execute(query: GetRandomStringsQuery, callback: (result: [String]) -> Void) { 
     var result = [String]() 

     for var i = 0; i < 100; i++ { 
      result.append("[\(i)]: \(query.prefix)") 
     } 

     callback(result: result) 
    } 

} 

Telefonvorwahl:

let query = GetRandomStringsQuery(prefix: "leak leak leak :(") 

let queryHandler = GetRandomStringsQueryHandler() 

queryHandler.execute(query) { (result) -> Void in 
    print("total records: \(result.count)") 
} 
+0

+1 für Refactoring mit Protokollen und Verknüpfen verknüpfter Abfrage- und Handler-Typen. Ich glaube nur, dass Sie vergessen haben, Ihre Typalias auf GetRandomStringsQueryHandler –

+0

zu definieren. Ich rate, dass der Compiler daraus schließen kann, was ich als Argument für die execute-Methode übergeben habe.Andernfalls hätte es ein Problem mit der Protokollkonformität ergeben. –

+0

Hallo, vielen Dank für die Erstellung der Protokollalternative für dieses Problem. Ich hoffe, dass Generika so schnell wie möglich behoben werden. – razor118