2015-09-18 16 views
7

私はswift iosアプリケーションでCQRSパターンを実装しようとしましたが、私は奇妙な動作を見つけました。スウィフト - ジェネリックスの問題原因メモリリーク

コアクラス:

class Query<T> {} 

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

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

の実装クラスの一覧:

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) 
    } 
} 

使用例:コールバックで

@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)") 
     } 
} 

我々は、アレイ内の100個の要素を取得する必要があります。実行時に参照が失われ、値が不明であるようです。 iOS Developer Instrumentsはメモリリークを検出します。

Weid behavaiorは、GetRandomStringsQueryHandlerからスーパークラスを削除し、実行関数から "override"修飾子を削除するとメモリリークが発生せず、アプリケーションがうまく動作します。

誰かがこの動作について説明できますか?それは私の間違いか迅速な問題ですか?

私は迅速2.

+0

どのようにメモリリークがあると決定されていますか?メモリが不足してクラッシュしている実際のデバイスで実行していますか?または楽器で確認するだけですか?楽器で確認したら、実際のデバイスやシミュレータを使用していますか?そしてどちらの方法でも、どのような記憶が漏れていると報告されていますか? – nhgrif

+0

今すぐアプリケーションを実行すると例外が発生します:libswiftCore.dylib'_swift_release_(swift :: HeapObject *)のEXC_BAD_ACCESS: デバイスとの接続でシミュレータを使用しています。 – razor118

+0

これはメモリリークとはちょっと違うので、おそらくあなたの質問に追加する必要があります。 – nhgrif

答えて

2

興味深い問題でのXcodeの最終verionを使用しています!私はあなたのコードをプレイグラウンドに貼り付け、あなたが遭遇したエラーを再現することができました。私はコードを微調整しようとしましたが、ジェネリックスを動作させることに失敗しました。代わりに、私は制約を表現するためにプロトコルを使用してコードを書き直すことになります。

コアプロトコル:

protocol QueryType { 
    typealias ResultType 
} 

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

準拠クラス:

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) 
    } 

} 

電話番号:

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

let queryHandler = GetRandomStringsQueryHandler() 

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

+1プロトコルとリファクタリング、関連するクエリとハンドラタイプのリンク。私はあなたがあなたのタイプアリアスをGetRandomStringsQueryHandlerで定義するのを忘れたと思います。 –

+0

私は、コンパイラが私が実行メソッドの引数として渡したものに基づいて推測できると推測しています。さもなければ、それはプロトコル準拠の問題を提起するでしょう。 –

+0

こんにちは、この問題の代替プロトコルを作成していただきありがとうございます。ジェネリック薬ができるだけ早く摂れることを願っています – razor118

関連する問題