web-dev-qa-db-ja.com

UIWindowのrootViewControllerの変更

アプリが最初に読み込まれるときに、rootViewControllerUIWindowプロパティをcontrollerAに設定します。

アプリの途中で、rootViewControllercontrollerBに変更することにしました。

問題は、controllerBでフリップトランジションを実行すると、その背後にcontrollerAのビューが表示されることがあるということです。何らかの理由で、そのビューは削除されていません。さらに心配なのは、rootViewControllercontrollerBに設定した後、controllerAdeallocメソッドが起動されないことです。

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;
}
25
aloo

2つの別々の問題があることがわかりました。 1)コントローラーAに保持サイクルがあったため、割り当てが解除されることはありませんでした。次に、ルートビューコントローラーを変更するには、最初にWindowsサブビューを削除する必要があります(ドキュメントで別の方法が提案されている場合でも)

10
aloo

問題はControllerAまたはControllerBの実装にある可能性があり、コード内に「self」が保持されている可能性があるため、ARCはViewControllerの割り当てを自動的に解除できません。 ControllerAとControllerBの実装を投稿できますか。

1
ntus1017

さらに簡単な解決策は、新しいウィンドウのbackgroundColor.whiteまたは任意の色に設定することです。デフォルトはnilで、背景が透明になります。そのため、古いウィンドウ(その上に新しいウィンドウが表示されます)が透けて見えます。

0
hoshy
var loginNavigationController: OnBoardViewController?{
    willSet{
        if newValue == nil {
            loginNavigationController?.view.removeFromSuperview()
        }
    }
}

loginNavigationController = nil

0
Ankish Jain

これは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のビューが割り当て解除されることはありません。

0
渺小的我