2 つのタブを持つ UITabBarController があります。TAB A は UIViewController で、TAB B は nib からロードされた UIViewController です。
TAB B から TAB A に移動したとき、または TAB B から他のタブに移動したときに、TAB B を初期状態にリセットしたいと考えています。これを行うには、新しいものを作成し、それを viewControllers 配列で置き換えます。問題は、UIViewController をリセットした後、「メッセージが割り当て解除されたインスタンスに送信されました。通常、次の 2 つのエラーのいずれかです。
*** -[AddCompetitionViewController isEqual:]: message sent to deallocated instance...
*** -[AddCompetitionViewController retain]: message sent to deallocated instance...
これは、TAB B から TAB A に切り替えた直後に発生します。
これは、タブを問題を切り分けるために使用しているコードです。
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
NSLog(@"Should Select: %@", viewController);
return YES;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSLog(@"Did Select: %@", viewController);
if ([viewController class] != [AddCompetitionViewController class]) {
AddCompetitionViewController *ACViewController = [[AddCompetitionViewController alloc] initWithNibName:@"AddCompetition" bundle:[NSBundle mainBundle] andDancer:self.currentDancer];
UITabBarItem *ACitem = [[UITabBarItem alloc] initWithTitle:@"Add Comp." image:[UIImage imageNamed:@"Addcomp.png"] tag:0];
ACViewController.tabBarItem = ACitem;
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray:self.viewControllers];
[arr replaceObjectAtIndex:1 withObject:ACViewController];
[self setViewControllers:arr];
NSLog(@"Replaced: %@", [arr objectAtIndex:1]);
}
}
(私はARCを使用しています)
NSLogs を使用して、TAB A に戻ろうとすると、アプリは新しいものではなく、古い元の UIViewController を参照しようとしていることを確認できました。tabBarController:didSelectViewController: は最後に呼び出されるものです。置換後に UIViewController を参照するコードは何もありません。また、例外ブレークポイントを追加しようとしましたが、それは一連の 16 進データをリストするだけで、デフォルトでアプリケーションのメインになります。ここに私のログがあります:
2012-08-18 16:20:05.479 How's My Feisin'[4780:c07] Should Select: <AddCompetitionViewController: 0x78a5af0>
2012-08-18 16:20:05.489 How's My Feisin'[4780:c07] Did Select: <AddCompetitionViewController: 0x78a5af0>
2012-08-18 16:20:06.885 How's My Feisin'[4780:c07] Should Select: <CompetitionListViewController: 0x78a7550>
2012-08-18 16:20:06.887 How's My Feisin'[4780:c07] Did Select: <CompetitionListViewController: 0x78a7550>
2012-08-18 16:20:06.887 How's My Feisin'[4780:c07] Replaced: <AddCompetitionViewController: 0x6c5d0f0>
2012-08-18 16:20:09.290 How's My Feisin'[4780:c07] *** -[AddCompetitionViewController retain]: message sent to deallocated instance 0x78a5af0
そしてバックトレース:
* thread #1: tid = 0x1c03, 0x017cddee CoreFoundation`___forwarding___ + 206, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x017cddee CoreFoundation`___forwarding___ + 206
frame #1: 0x017cdcb2 CoreFoundation`_CF_forwarding_prep_0 + 50
frame #2: 0x0176e2c0 CoreFoundation`CFRetain + 96
frame #3: 0x01798ab9 CoreFoundation`CFArrayApplyFunction + 57
frame #4: 0x0072ffbb UIKit`_afterCACommitHandler + 255
frame #5: 0x0183b99e CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
frame #6: 0x017d2640 CoreFoundation`__CFRunLoopDoObservers + 384
frame #7: 0x0179e4c6 CoreFoundation`__CFRunLoopRun + 1174
frame #8: 0x0179dd84 CoreFoundation`CFRunLoopRunSpecific + 212
frame #9: 0x0179dc9b CoreFoundation`CFRunLoopRunInMode + 123
frame #10: 0x01c447d8 GraphicsServices`GSEventRunModal + 190
frame #11: 0x01c4488a GraphicsServices`GSEventRun + 103
frame #12: 0x0071f626 UIKit`UIApplicationMain + 1163
frame #13: 0x00002595 How's My Feisin'`main + 181 at main.m:16
frame #14: 0x000024d5 How's My Feisin'`start + 53
このエラーを見つけたり、UIViewController を置き換えるためのより良い場所を見つけたりするのに役立ちます! ありがとう!
編集: 問題の原因を突き止めましたが、まだ修正する方法がありません。UITabBarController がビューの変更をアニメーション化するのを見たことがありませんが、それでもアニメーションを実行しているようです。アプリのプロファイリングに成功し、_afterCACommitHandler がオブジェクトに対して追加のリリースを実行しています。
編集:回避策を見つけました。別の UIViewController を tabBarController と TAB B の UIViewController の間に配置しました。その後、新しい UIViewController で古いものをリセットしました。それは機能しますが、物事を行う正しい方法ではありません。そして、何が余分なリリースを引き起こしたのかはまだわかりません。