2016-04-25 9 views
2

私はiosの開発に慣れていません。メモリリークがswiftまたはObjective-Cにどのように発生するかを知りたいと思っています。迅速なメモリリークの発生方法

おかげ

+1

低いAPIで再生する保持サイクル(CGReleaseStuffなど自分で呼びたいCGPathなど) – Larme

+1

'retain cycles' - 互いに強い参照を保持する複数のオブジェクト:' A'は ' 「B」は「A」を参照する。 – luk2302

答えて

9

小さな例:

class A { 
    var b: B! 

    deinit { 
     print("deinit of A") 
    } 
} 

class B { 
    var a: A! 

    deinit { 
     print("deinit of B") 
    } 
} 

do { 
    let a = A() 
    let b = B() 
    a.b = b 
    b.a = a 
} 

をあなたが(多分遊び場に)このコードを実行した場合、それは何も印刷されません。それは、deinitが両方のオブジェクトに対して決して呼び出されず、単に漏れたことを意味します。

しかし、あなたがweakとしての特性のいずれかを宣言した場合:

class A { 
    weak var b: B! 

    deinit { 
     print("deinit of A") 
    } 
} 

を次にdeinitが呼び出されると、コンソールにメッセージが表示されます。

編集:閉鎖

この例を考えてみましょうとの例を追加します。

class C { 
    var f: (Void -> Void)! 

    deinit { 
     print("deinit for C") 
    } 
} 

do { 
    let c = C() 
    c.f = { 
     print(c) 
    } 
} 

cfcを取り込み、fをキャプチャします。だから我々はメモリリークを得た。

クロージャのリークを処理するには、キャプチャされたオブジェクトがweakまたはunownedであることを宣言します。 ;オブジェクトが存在抜け出すとクロージャが呼び出されたときにnilになるすることが可能かどう

do { 
    let c = C() 
    c.f = { [weak c] in 
     print(c) 
    } 
} 

基本的に、あなたはweakを使用します。このようなこの時点でオブジェクトが存在することが確かな場合は、代わりにunownedを使用してください。

cを閉鎖内にweakと宣言した後、「deinit for C」が表示されます。つまり、すべてが正常に割り当て解除されたことを意味します。

このすべての意味は、開発者ですか?

ほとんどすべての時間は、メモリ管理について心配する必要はありません。それはあなたのために自動的に行われます。オブジェクトは必要なときにだけ存在し、そうでないときには消えます。しかし、2つの非常に一般的な場合は注意する必要があり、メモリについて考える必要があります。

  1. 委任。それはココアの一般的なパターンであり、間違っていれば保持サイクルを作り出すことができます。正当な理由がない限り、常に代理人をweakと宣言してください。
  2. クロージャ。クロージャは、周囲のスコープ内のオブジェクトの参照をキャプチャし、自動的に通知します。クロージャを実装するときは、保持サイクルを作成するかどうかを確認します。はいの場合は、問題の変数をweakまたはunownedと宣言します。

詳細情報iBooksまたはhereの公式Apple Swiftブックをウェブサイトで読むことをお勧めします。

+0

あなたの例をありがとう。これに関する情報が必要です。この1つのケースにはメモリだけが漏れますか?または任意の他の条件のリストがメモリリークが発生する可能性があります。 – iosLearner

+0

また、メモリリークが発生する可能性があります。私はより多くの情報を与えるために私の答えを編集します。 –