アプリが最初に読み込まれるときに、rootViewController
のUIWindow
プロパティをcontrollerA
に設定します。
アプリの途中で、rootViewController
をcontrollerB
に変更することにしました。
問題は、controllerB
でフリップトランジションを実行すると、その背後にcontrollerA
のビューが表示されることがあるということです。何らかの理由で、そのビューは削除されていません。さらに心配なのは、rootViewController
をcontrollerB
に設定した後、controllerA
のdealloc
メソッドが起動されないことです。
UIWindow
に切り替える前に、controllerB
のサブビューを手動で削除しようとしました。これにより、controllerA
のビューがバックグラウンドで表示される問題が解決しますが、controllerA
のdeallocは引き続き表示されます。呼び出されることはありません。 ここで何が起こっているの????
リンゴのドキュメントは言う:
ルートビューコントローラは、ウィンドウのコンテンツビューを提供します。 View Controllerをこのプロパティに(プログラムでまたはInterface Builderを使用して)割り当てると、ViewControllerのビューがウィンドウのコンテンツビューとしてインストールされます。ウィンドウに既存のビュー階層がある場合、新しいビューがインストールされる前に古いビューが削除されます。
[〜#〜] update [〜#〜]
これが私のAppDelegateのコードです:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self showControllerA];
[self.window makeKeyAndVisible];
return YES;
}
- (void)showControllerA
{
ControllerA* a = [ControllerA new];
self.window.rootViewController = a;
}
- (void) showControllerB {
ControllerB* b = [ControllerB new];
self.window.rootViewController = b;
}
2つの別々の問題があることがわかりました。 1)コントローラーAに保持サイクルがあったため、割り当てが解除されることはありませんでした。次に、ルートビューコントローラーを変更するには、最初にWindowsサブビューを削除する必要があります(ドキュメントで別の方法が提案されている場合でも)
問題はControllerAまたはControllerBの実装にある可能性があり、コード内に「self」が保持されている可能性があるため、ARCはViewControllerの割り当てを自動的に解除できません。 ControllerAとControllerBの実装を投稿できますか。
さらに簡単な解決策は、新しいウィンドウのbackgroundColor
を.white
または任意の色に設定することです。デフォルトはnilで、背景が透明になります。そのため、古いウィンドウ(その上に新しいウィンドウが表示されます)が透けて見えます。
var loginNavigationController: OnBoardViewController?{
willSet{
if newValue == nil {
loginNavigationController?.view.removeFromSuperview()
}
}
}
loginNavigationController = nil
これはAppleのバグであり、現在のrootViewControllerとしてViewControllerAを想定しています。
// ViewControllerA.m
- (void)buttonClick {
[self dismissViewControllerAnimated:YES completion:^{
// [((AppDelegate *)[[UIApplication sharedApplication] delegate]) resetRoot]; // OK
}];
[((AppDelegate *)[[UIApplication sharedApplication] delegate]) resetRoot]; // ViewControllerA's view will not dealloc
}
// AppDelegate.m
- (void)resetRoot {
ViewControllerB *controller = [[ViewControllerB alloc] init];
self.window.rootViewController = controller;
}
このコードとしてウィンドウのrootViewControllerをリセットすると、ViewControllerAのビューが割り当て解除されることはありません。