質問

私がよく目にする一般的な慣行は次のとおりです(非常に人気のあるiPhone開発者の本を含む)

.hファイル内:

@interface SomeViewController : UIViewController
{
  UIImageView *imgView;
}

.mファイルのどこか:

imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]
applicationFrame]];
[imgView setImage:[UIImage imageNamed:@"someimage.png"]];
[self addSubview:imgView];
[imgView release];

その後、これが表示されます...

- (void) dealloc
{
  [imgView release];
  [super dealloc];

} 

imgViewには対応するallocとリリースがあるため、deallocでのimgViewのリリースは必要ですか?

addSubview呼び出しによって保持されるimgViewはどこにありますか?

役に立ちましたか?

解決

はい、そのコードには問題があります。 imgViewのリリースが早すぎるため、まれにクラッシュが発生する可能性があります、オブジェクトを保持せずにインスタンス変数に保存します。通常、メモリ管理は間違った方法で行われます。

これを行う正しい方法の1つは次のとおりです。

@interface SomeViewController : UIViewController
{
    UIImageView *imgView;
}
@property (nonatomic, retain) UIImageView *imgView;

そして実装;

@synthesize imgView;

モジュール内のどこか:

//Create a new image view object and store it in a local variable (retain count 1)
UIImageView *newImgView = [[UIImageView alloc] initWithFrame:self.view.bounds];
newImgView.image = [UIImage imageNamed:@"someimage.png"];

//Use our property to store our new image view as an instance variable,
//if an old value of imgView exists, it will be released by generated method,
//and our newImgView gets retained (retain count 2)
self.imgView = newImgView;

//Release local variable, since the new UIImageView is safely stored in the
//imgView instance variable. (retain count 1)
[newImgView release];

//Add the new imgView to main view, it's retain count will be incremented,
//and the UIImageView will remain in memory until it is released by both the
//main view and this controller. (retain count 2)
[self.view addSubview:self.imgView];

そして、deallocは同じままです:

- (void) dealloc
{
    [imgView release];
    [super dealloc];
}

他のヒント

コードが正しくありません。割り当てが解除されると、 imgView が解放されます。

.mファイルでは、次のことができます。

  1. alloc it->あなたがそれを所有している
  2. サブビューとして追加->あなたと UIViewが所有している
  3. release it->あなたはそれを所有していない

dealloc では、上記の手順3で確立したように、所有者ではないにもかかわらずimgViewを release します。 [super dealloc] を呼び出すと、ビューはすべてのサブビューを解放し、例外が発生することを想像します。

imgView のivarを保持したい場合は、サブビューとして追加した後に release を呼び出さないでください。 dealloc も同じです。そうすれば、 imgView がビュー階層からある時点で削除されたとしても、それへの有効な参照が残っています。

コードが間違っています。deallocが呼び出されたときにinitメソッドで解放しないでください(ivarとして保持する場合は、ポインタを必要としない限り、その必要はありません) addSubview:がビューを保持するため、他の場所で)。

実際にクラッシュしない理由は、(addSubview:の呼び出しから)スーパークラスによってまだ保持されているためだと思います。ビューはおそらく、直後に割り当てが解除されるとスーパービューから自身を削除するため、 [super dealloc] が呼び出されてもオーバーリリースされません。それは私の予感です、リースで。

initのリリースは正しくありません。

「一般的な慣行」に言及しました名前のない本。 Appleの標準的な例を参照することをお勧めします。ViewTransitionsは、この場合の良い例です(起動する2つのビュー;)

http://developer.apple.com/iphone/library /samplecode/ViewTransitions/index.html

コメントを追加するほどの評判はまだありません。)

@bentford:間違っている場合は修正してください。ただし、imgViewプロパティの合成セッターを使用するには、" self.imgView"を使用する必要があると思います:

self.imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]

自己を持っていない場合、それは単にivarを使用しているだけであり、追加の保持を取得していません。

基本的な答えは、サンプルコードに [imgView release] が1つしかないことです( addSubviewの後かdeallocにあるか)。ただし、 dealloc から [imgView release] を削除し、 addSubview の後に残します。

iPhoneには問題があります。 didReceiveMemoryWarning を使用すると、オブジェクト(ビュー全体を含む)を下から解放できます。アプリケーション全体の保持セットがあり、メモリを尊重しない場合は、アプリケーションが強制終了されるだけです。

良い例:
ネストされた3つのビューのセットを考える場合、ビュー1->表示2->表示3。 次に、「 viewDidLoad 」および「 viewDidUnload 」の呼び出しを検討します。ユーザーが現在「ビュー3」にいる場合、View1がアンロードされている可能性があります。これが厄介な場所です。
  viewDidLoad 内でオブジェクトを割り当て、サブビューに追加した後に解放しなかった場合、view1がアンロードされてもオブジェクトは解放されませんが、view1はまだアンロードされます。
  viewDidLoad が再度実行され、コードが再度実行されますが、オブジェクトのインスタンス化は1つではなく2つになりました。 1つのオブジェクトは、以前にアンロードされたビューを持つどこにも存在せず、新しいオブジェクトは現在表示されているビュー用になります。すすぎ、泡立て、繰り返します。メモリリークによりアプリケーションがクラッシュします。

この例では、指定されたコードブロックが揮発性であり、再度実行される可能性がある場合(メモリまたはアンロードされたビュー)、 [imgView release ]; deallocからaddSubViewの後に残します。

基本的な保持/リリースの概念に関するリンクは次のとおりです。 http://www.otierney.net/objective-c.html#retain

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top