2

現在、ナビゲーション ベースのアプリケーションがあり、明らかに RootViewController は UITableView です。ただし、UITableView の上に浮かぶ UIToolbar を作成する必要があると判断しました。現在、私はこれをこのようにしています。

- (void)viewWillAppear:(BOOL)animated {

 [super viewWillAppear:animated];


 //Initialize the toolbar 
 toolbar = [[UIToolbar alloc] init]; 
 toolbar.barStyle = UIBarStyleDefault;

 //Set the toolbar to fit the width of the app. 
 [toolbar sizeToFit];

 //Caclulate the height of the toolbar 
 CGFloat toolbarHeight = [toolbar frame].size.height;

 //Get the bounds of the parent view 
 CGRect rootViewBounds = self.parentViewController.view.bounds;

 //Get the height of the parent view. 
 CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds);

 //Get the width of the parent view, 
 CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds);

 //Create a rectangle for the toolbar 
 CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight, rootViewWidth, toolbarHeight);

 //Reposition and resize the receiver 
 [toolbar setFrame:rectArea];

 //Create a button 
 UIBarButtonItem *infoButton = [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(account_details)];

 [toolbar setItems:[NSArray arrayWithObjects:infoButton,nil]];

 //Add the toolbar as a subview to the navigation controller. 
 [self.navigationController.view addSubview:toolbar];
 [infoButton release];

 [self.tableView reloadData];

}

しかし、Leaks インストゥルメント ツールを使用した後、これがいくつかのメモリ リークの原因であると判断できました。それにもかかわらず、メモリ リークはごくわずかでした。次に、さらに掘り下げて、メモリ リークの原因となっている正確な行を特定することができました。それらは次のとおりです。

UIBarButtonItem *infoButton = [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(account_details)];

 [toolbar setItems:[NSArray arrayWithObjects:infoButton,nil]];

 [self.navigationController.view addSubview:toolbar];

これらのメモリ リークを取り除く方法を見つけ出すのに苦労しているため、アプリケーションがよりスムーズに実行されます。上記の行がリークを引き起こしている理由について、何か助けていただければ幸いです。

4

1 に答える 1

3

ビューが表示されるたびに新しいツールバーが作成され、ビューに追加され、解放されることはありません。これは、そのツールバーとそのバー ボタン項目の両方が永久に存続することを意味します。ビューにツールバーを追加した後にツールバーを解放するか、作成時に自動解放メッセージを送信するだけで、これを修正できます。したがって、これを行う適切な方法は、次のように置き換えることです。

toolbar = [[UIToolbar alloc] init];

と:

toolbar = [[[UIToolbar alloc] init] autorelease];

また、これを行う方法では、ビューが表示されるたびに、別のツールバーをナビゲーション コントローラーのビューに追加することになります。したがって、これらのオブジェクトのかなりの数が互いに重なり合っていることはほぼ確実です (そのため、ナビゲーション ビューが最終的になくなるまで、リークは引き続き表示されます)。このツールバーを ivar として保持することもできます。ビューが消えたら、ナビゲーション コントローラーのビューからツールバーを削除します。表示されたら追加します。メソッドでツールバー自体を作成し、それviewDidLoadをクリーンアップしてviewDidUnloadから、dealloc で解放します。したがって、新しいクラスは次のようになります (retain である toolbar という名前の合成プロパティを作成すると仮定します)。

- (void)viewDidLoad
{
  [super viewDidLoad];
  UIToolbar* toolbar = [[[UIToolbar alloc] init] autorelease];
  // set up toolbar
  [self setToolbar:toolbar];
  // other load code
}

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  [[[self navigationController] view] addSubview:[self toolbar]];
  // other vwa code
}

- (void)viewDidDisappear:(BOOL)animated
{
  [super viewDidDisappear:animated];
  [[self toolbar] removeFromSuperview];
}

- (void)viewDidUnload
{
  [self setToolbar:nil];
  [super viewDidUnload];
}

- (void)dealloc
{
  UIToolbar* toolbar = [self toolbar];
  [toolbar removeFromSuperview]; // shouldn't ever need this, but be safe
  [toolbar release];
  // other dealloc
  [super dealloc];
}
于 2010-11-10T02:49:09.430 に答える