2009-09-06 13 views
5

多くのiPhoneコードサンプル(Appleなどから)には次のようなコードが含まれています。目的C:uiオブジェクトを作成した直後に解放する理由

- (void)viewDidLoad { 
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; 

// add the top-most parent view 
UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 
contentView.backgroundColor = [UIColor blackColor]; 
self.view = contentView; 
[contentView release]; 

levelView = [[LevelView alloc] initWithFrame:applicationFrame viewController:self]; 
[self.view addSubview:levelView]; 

calibrationView = [[CalibrationView alloc] initWithFrame:applicationFrame viewController:self]; 
} 

このスニペットはBubbleLevelサンプルプロジェクトのものです。

私の質問:なぜリリースメッセージがcontentViewに送信されるのですか? self.view内のcontentViewへの参照は保持されています。このメソッドだけでなく、アプリケーションの存続期間中も明らかに使用したいと考えています。呼び出しを解放しないとビューが解放されませんか?

+0

皆様、ありがとうございます。 –

答えて

6

retain/releaseとは、単に均衡するものとはみなされません。彼らがしているのは所有権を移譲することです。所有権の考え方を理解し、Cocoaのメモリ管理について理解しています。

所有権はスコープ内で設定されます。メソッドスコープ、オブジェクトインスタンススコープ、またはグローバルアプリケーションスコープです。メソッドは、ローカル変数を保持することによってを所有します。オブジェクトインスタンスは、保持されたインスタンス変数を持つことによってを所有します。また、アプリケーションは、保持されているグローバル変数を持つことによってを所有しています。

現在の方法は、あなたがallocという名前のメソッド呼び出しからそれを受け取った場合は、オブジェクトを所有している、または新しい単語が含まれているか(newSprocketまたはmutableCopyのように)をコピーします。他の方法であなたに与えられたすべてのオブジェクトは、あなたのメソッドへの引数や結果がほとんどのメソッド呼び出しのようにあなたが所有していません。

自分が所有していないオブジェクトインスタンスにアクセスできます。オブジェクトインスタンスが現在のメソッドの実行を過ぎても存続するようにするには、retainで明示的に所有権を取得する必要があります(実行する場合はrun-loop)

このコード行は、ローカル変数contentViewから参照されるオブジェクトインスタンスの所有権を取得します。メソッドloadViewがオブジェクトを所有するようになりました。

UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 

次に、プロパティが保持されていると宣言されているため、オブジェクトインスタンスselfは所有権を取得します。オブジェクトインスタンスにメソッドとクラスの2つの所有者が追加されました。

self.view = contentView; 

ここからは、このメソッドのローカル変数を使用してビューオブジェクトにアクセスすることはありません。メソッドはもはやそれを必要としないので、所有権を辞退します。現在、オブジェクトはオブジェクトインスタンスによってのみ所有されており、このメソッドの場合はの問題ではなくなりました()。

[contentView release]; 
+0

大きな説明。 しかし、最初にインスタンスを割り当てたので、インスタンスを解放する必要があることを強調することをお勧めします。あなたがそれをもう必要としないだけでなく、メソッドの最後にローカル変数へのアクセスを失うこともあります。 –

8

いいえ、self.view = contentViewはそれを保持します。また、保留と解放のバランスを取る必要があるので、解放する必要があります。

5

他の言語に慣れている場合は、self.view = contentViewを見て「ああ、インスタンス変数を割り当てています」と思うのは当然でしょう。 Objective-Cのオブジェクトは常にポインタなので、インスタンス変数にはドットを代入することはできません。これはプロパティアクセサーです。ほとんどの場合、それは正確に[self setView:contentView]と書くことと同じです。多くの場合

は、そのsetterメソッドは次のように実装されます:あなたはプロパティを設定するとき

- (void)setView:(UIView *)view { 
    if (view != _view) { 
     [_view release]; // where _view is the name of the actual instance variable 
     _view = [view retain]; 
    } 
} 

このような場合には、それが保持されています。したがって、オブジェクトをそこに解放する必要があります。そうしないと、オブジェクトの割り当てによって引き起こされる初期の所有権は決して解放されません。

13

Ölbaumは、self.view = contentView;があなたのビューを保持すると言って正しいです。つまり、割り当て解除されません。しかし、この動作は常にそうではありません。

あなたがのUIViewControllerのドキュメント(またはヘッダ)を見ると、あなたがviewプロパティは、次のように宣言されていることがわかります:

@property(nonatomic, retain) UIView *view; 

このビュープロパティが(foo.view = anotherViewまたは[foo setView:anotherView];)に設定されているときはいつでも、他のビューは保持されることを意味します。 viewプロパティは次のように宣言された場合:

@property(nonatomic, assign) UIView *view; 

次にビューはは保持されません。これは、インスタンス変数への単純なポインタ割り当てを行います。この場合、次のreleaseからcontentViewまでがビューを破壊することになります。つまり、コントローラが無効なポインタを持つことになり、アプリケーションがクラッシュする可能性があります。

つまり、プロパティを使用する場合、retainまたはassignかどうかを確認してください。 (それが言うなら、それはassignです)。それに応じてメモリ管理を行います。

関連する問題