15

Swift 2 (Xcode 7 beta 3) でアプリケーションを開発しており、可能な場合は値の型 (構造体と列挙型) を使用しようとしています。メモリ管理に関する Apple のドキュメントによると、値型を操作しても保持サイクルは発生せず、機能するはずです。

しかし、今日、イベント処理コードで大量のメモリ リークが発生しました。私はそれを追跡し、問題を次の最小限の例に減らしました。

Item単一のプロパティを定義するプロトコルがあるとしましょうvalue:

protocol Item {

    var value: String { get }

}

Item次に、プロトコルを実装し、追加のプロパティを追加する具体的な構造体を作成しますadditionalValue。struct を呼び出しましょうFooItem

struct FooItem<T>: Item {

    let value: String
    let additionalValue: T

    init(value: String, additionalValue: T) {
        self.value = value
        self.additionalValue = additionalValue
    }

}

パズルの 3 番目のピースは、Itemプロトコルを実装するアイテムをラップする別の構造体です。と呼ばれていItemWrapperます。

struct ItemWrapper {

    let item: Item

    init(item: Item) {
        self.item = item
    }

}

ItemWrapperメモリ リーク設定を使用して Instruments でプロファイリングすると、値が で作成されるたびにメモリ リークが発生しますFooItem

let item = FooItem(value: "protocol value", additionalValue: "foo item value")  
let _ = ItemWrapper(item: item) 

楽器のスクリーンショット 1 楽器のスクリーンショット 2

サンプルXcode プロジェクトInstruments ファイルは次のとおりです: https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0

コード例全体は、このGist で表示できます: https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a

バグレポートは次のとおりです: rdar://21375421

それは Swift コンパイラのバグですか、それとも何か間違ったことをしていますか?


EDIT 1 : コメントで示唆されているように、Swift コミュニティや言語の開発者からより多くの注目を集めるために、この質問をApple Dev Forumに再投稿しました。WWDC 2015 中に開発フォーラムが移行されたため、新しいフォーラムに更新された質問を投稿する必要がありました。リンクは次のとおりです: https://forums.developer.apple.com/message/9643


編集 2 : サンプル コードで最初に投稿した問題は、Swift 2.0で解決されたようです。私のアプリの問題は解決しなかったので、サンプル コードに別の変更を加えました。FooItemの追加のプロパティにはジェネリック型があり、FooItemその型で注釈が付けられているため、ジェネリック型です。これは私が自分のアプリで使用している方法であり、それでもメモリリークが発生しますが、今回ItemWrapperはプロパティにアクセスするときではなく、が初期化されるときです。


編集 3 : Swift 2.0 で持続する変更された問題に質問を完全に更新し、新しい Xcode プロジェクトの例をアップロードしました。

4

2 に答える 2

4

デベロッパー フォーラムでもバグ トラッカーでも Apple からの応答はなく、最新のベータ バージョンのリリース ノートでもこの問題に関連するものは見つかりませんでしたが、Swift コンパイラでは解決されているようです。Xcode 7 ベータ 5で。(ベータ 4 でも動作する可能性があります。私が確認した最後のバージョンはベータ 3 でした。)

デモ プロジェクトでは、メモリ リークは発生しなくなりました。同じことが私のアプリにも当てはまります。わーい!

ここに画像の説明を入力

于 2015-08-11T08:08:22.673 に答える
3

さて、これが回避策ですが、なぜ機能するのかわかりません。これを行うと、次のことに気付きました。

    let theItem = itemWrapper.item
    let value = theItem.value

...これの代わりに:

    let value = itemWrapper.item.value

...メモリリークは発生しません。

于 2015-06-04T21:51:38.000 に答える