2011-01-06 14 views
0

私はiPhoneアプリケーションをプログラミングしています。自分のメソッドの1つでメモリ管理に関する質問がありました。私はまだ手作業でメモリを管理するのがちょっと新しいので、この質問が初心者に見えるのならごめんなさい。Objective-Cメソッドの適切なメモリ管理

以下は、数字パッドがタグに基づいてラベルにボタンを配置できるように設計された方法です。この方法でボタンごとにメソッドを作成する必要はありません。このメソッドはうまくいきますが、私が関数内で作る変数を解放するのかどうかは疑問です。

変数を解放しようとするとアプリケーションがクラッシュするため、メモリに関する私の責任について少し混乱します。

FYI変数firstValueは私のラベルであり、それはこの方法で宣言されていない唯一の変数です:

ここに方法があります。

-(IBAction)inputNumbersFromButtons:(id)sender { 
    UIButton *placeHolderButton = [[UIButton alloc] init]; 
    placeHolderButton = sender; 

    NSString *placeHolderString = [[NSString alloc] init]; 
    placeHolderString = [placeHolderString stringByAppendingString:firstValue.text]; 

    NSString *addThisNumber = [[NSString alloc] init]; 
    int i = placeHolderButton.tag; 

    addThisNumber = [NSString stringWithFormat:@"%i", i]; 

    NSString *newLabelText = [[NSString alloc] init]; 
    newLabelText = [placeHolderString stringByAppendingString:addThisNumber]; 

    [firstValue setText:newLabelText]; 

    //[placeHolderButton release]; 
    //[placeHolderString release]; 
    //[addThisNumber release]; 
    //[newLabelText release]; 

} 

最後の4行がコメントアウトされていてもアプリケーションはうまく動作しますが、ここでこれらの変数を解放する必要があるようです。もし私がそれについて間違っていたら、関数で宣言された変数をいつリリースする必要があるのか​​、そうでないのかについての簡単な説明を歓迎します。ありがとう。

答えて

3

はい、それらを解放する必要がありますが、機能の最後をはるかに超えて少し長めにする必要があります。

解決策は、autoreleaseと呼ばれます。 releaseautoreleaseに置き換え、プログラムがrunloopに戻ってくるまで、オブジェクトはそのまま残ります。

プログラムがそこに戻ってくると、オブジェクトの1つに興味がある人は誰でもretainメッセージを送信していたはずです。したがって、NSAutoreleasePoolでオブジェクトを解放するとオブジェクトは解放されません。

実際には、あなたのコードを見れば、もっと間違っています。例えば。これは

UIButton *placeHolderButton = [[UIButton alloc] init]; 
placeHolderButton = sender; 

は意味がありません。最初にオブジェクトを割り当ててから、ポインタを変数placeHolderButtonに割り当てます。それはいいです。

次に同じ変数にsenderを割り当てます。今作成したオブジェクトへの参照が失われました。

-(IBAction)inputNumbersFromButtons:(id)sender { 
    UIButton *placeHolderButton = sender; // this is still a little useless, but ok 

    int i = placeHolderButton.tag; 
    NSString *addThisNumber = [NSString stringWithFormat:@"%i", i]; 

    NSString *placeHolderString = firstValue.text; 

    NSString *newLabelText = [placeHolderString stringByAppendingString:addThisNumber]; 

    [firstValue setText:newLabelText]; 
} 

ませallocs、必要ありませんのでリリース:私はあなたが望む結果を得るていないが、これは良いだろう場合はわからない

。これらの関数によって返された文字列はすでにautoreleasepoolに追加されているため、必要に応じて自動的に割り当てが解除されます。

+0

ああ、ありがとう、ありがとうございます。ちょうど不思議なことに、いつautoreleaseプールが解放されるのですか?これがすべてのプログラムに固有の質問であれば、本当に重要ではありません。 – Justin

+0

@ジャスティン:申し訳ありませんが、あなたのコードを実際に見るために 'release'という質問に答えるのは早すぎました。いくつかの問題がありましたが、私は答えにきれいなバージョンを追加しました。 – mvds

+0

autoreleaseプールは、現在の実行ループの最後に "将来のある時点で"排水されます。これを見るための最も簡単な方法は、中括弧の間のものはすべて問題ありませんが、中括弧の外側で使用したい場合は、それを保持する必要があります。 – MCannon

0

あなたがそれらを完了したら、それらをリリースします。早いほど良い。いくつかのオブジェクトは、メモリ管理を初めて使う人にとっては難解です。

deallocメソッドでそれらを解放します。

自動リリースプールは便利なことがありますが、パフォーマンス上の問題では不一致になることがあります。

0

new、alloc/initまたはcopyという単語を含むものをすべてリリースする必要があります。

また、あなたはこのINIT/ALLOCする必要はありません。

UIButton *placeHolderButton = [[UIButton alloc] init]; 
placeHolderButton = sender; 

これを行うための別の方法がある:あなたのバージョンで

UIButton *placeHolderButton = (UIButton *)sender; 

、それが保持してインスタンスを割り当てています+1のカウントが、すぐに参照を置き換えているので、後でメモリを解放する方法はありません。

alloc/initを使用して多数のインスタンスを作成し、それらの参照を自動リリースされたインスタンスに置き換えます。

あなたは

NSString *placeHolderString = [placeHolderString stringByAppendingString:firstValue.text]; 

の代わりに、再び第二の自動解放のインスタンスで、最初の行に作成された手動で管理インスタンスを置き換えている

NSString *placeHolderString = [[NSString alloc] init]; 
placeHolderString = [placeHolderString stringByAppendingString:firstValue.text]; 

を使用することができます。

infactこれでは、すべてのalloc/initをファクトリメソッドに置き換えることができ、オートレリースされたインスタンスと同じように、メモリをすべて処理する必要はありません。

-(IBAction)inputNumbersFromButtons:(id)sender { 
    //cast sender as a UIButton to suppress compiler warning, and allow us to reference it as placeholder button 
    UIButton *placeHolderButton = (UIButton *) sender; 

    int i = placeHolderButton.tag; 

    NSString *addThisNumber = [NSString stringWithFormat:@"%i", i]; 
    [firstValue setText:[firstValue.text stringByAppendingString:addThisNumber]]; 
} 

あなたはNSStringのためのクラスのドキュメントを見てみると、+その隣(すなわち+ stringWithString:(NSStringの*)の文字列)を持つ任意のメソッドは、クラスメソッドで、参照にこれらのメソッドを使用していませんあなたがalloc/initを呼び出した後です。

+0

本当に私のためにそれをクリアした答えをありがとう – Justin

0

UIButtonでalloc/initを使用することに困惑しています。

私は常にファクトリメソッドを使用します。

UIButton* aButton = [UIButton buttonWithType:UIButtonTypeCustom]; 

これは、目的の親ビューに直ちに追加する自動再生ボタンを返します。

これは現在のところ確認できませんが、SDKがUIButtonインスタンスをキャッシュし、その場で最適化を行っているかのように見えます。 UIButton ivarを保持しようとするたびに、パフォーマンスが低下しました(特に、画面に多数のサブビューがある場合)