警告:-切り離されたビューコントローラーでのビューコントローラーの表示は推奨されません


180

私のアプリでは、ナビゲーションコントローラーを使用しています。後でいくつかのビューpresentViewControllerで、ズームした画像を表示するために使用しています。また、ストーリーボードやペン先は使用していません。

このエラーはiOS 7でのみ発生します。iOS 6以前では正常に動作します。

切り離されたView ControllerにView Controllerを提示することはお勧めしません


まだわかりませんでした。しかし、私のアプリでは、window.rootviewcontrollerにビューコントローラーを割り当てていません。ウィンドウにビューを追加しています。それが私の理由かもしれません。確かではありません...
Gagan Joshi

@GaganJoshi上記の理由が原因ではない可能性があります。私も同じ問題に直面しています。私たちのプロジェクトでは、viewコントローラーをwindow.rootviewcontrollerに割り当てています。
Rajesh

1
他のコメントは、これをrootViewControllerとウィンドウ接続に関するものに正しく関連付けていると思います。私はそれを完全に理解していませんが、ナビゲーションコントローラーまたはその子の1つではなく、rootViewControllerに直接コントローラーを表示することで問題を回避することができました。
Rich Waters

Azaxisがそれを手に入れました:stackoverflow.com/a/31877722/5306470
Daniel Springer

回答:


207

プッシュナビゲーションで警告が表示されないようにするには、直接使用できます。

[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];

そして、モーダルビューコントローラーで、すべてが完了したら、次のように呼び出すだけです。

[self dismissViewControllerAnimated:YES completion:nil];


私はこの行コード "[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];"でイメージピッカーを提示しています。しかし、この行 "[self dismissViewControllerAnimated:YES completion:nil];"でポーカービューを閉じることができません。dismisscontrollerの代替オプション
kb920

@keyurbhalodiya機能させるには、modalViewからdismissViewControllerメソッドを呼び出す必要があります。したがって、[viewA.window.rootViewController presentViewController:viewB]を使用して、viewAからviewBという名前のビューを表示した場合、viewBで、たとえば、[self dismissViewControllerAnimated]を呼び出すカスタムアクションに関連付けられたボタンを追加する必要があります。より明確ですか?
cdescours 2014

11
iOS 8でビューコントローラーを表示しない
Rajesh Maurya

1
iOS 8の場合:[self.view.window.rootViewController.navigationController
Fede Cugliandolo

31
使用self.navigationControllerしてくれました。
Brandon Zacharie、2015年

62

この警告の理由は、フルサイズのビューではない小さなビューの上にビューコントローラーを表示していたためです。以下は私のプロジェクトのイメージです。上の4つのオプションをクリックしてください。ユーザーは別のchildviewcontrollerのビューに移動します(tabViewcontrollerのように機能します)。ただし、childviewcontrollerには小さなサイズのビューが含まれています。そのため、childviewcontrollerからビューを提示すると、この警告が表示されます。

マスター詳細ビュー

これを回避するには、childviewcontrollerの親にビューを表示できます

  [self.parentViewController presentViewController:viewController animated:YES completion:nil];

1
[self.view.window.rootViewController.navigationController pushViewController:YOUR_VIEW_CONTROLER animated:YES];
Fede Cugliandolo 2014

1
「フルサイズのビューではない小さなビューの上にビューコントローラを表示していました。」... 丁度。よくやった。
Fattie

61

待つviewDidAppear()

このエラーは、ビューを実際に表示する前にビューコントローラーを表示しようとした場合にも発生しますviewWillAppear()。その後ろviewDidAppear()または内部に別のビューを表示してみてください。


9
言い換えればviewDidLoad()、人々にビューコントローラを表示しないでください!私は何度もこの間違いを犯しました...
Tブランク

これは助けてくれてありがとう。最後にダイアログを表示しようとするviewDidLoadにコードがありました。
ArdenDev 2016

アニメーションでテストしない単体/統合テストを実行すると、このエラーが発生します。
mixtly87 2016年

21

私の場合、sampleViewControllerサブビューとして追加されたのビューを使用して、ビューsampleViewController(ここselfではUIViewControllerインスタンス)からポップオーバーを表示しようとします。

[self.view addSubview:sampleViewController.view];

正しい方法は以下のとおりです。

// make sure the vc has been added as a child view controller as well
[self addChildViewController:sampleViewController];
[self.view addSubview:sampleViewController.view];
[sampleViewController didMoveToParentViewController:self];

ところで、これは、テーブルビューセルからポップオーバーを表示する場合にも機能します。テーブルビューコントローラが子ビューコントローラとして追加されていることを確認するだけです。


さらに、didMoveToParentViewControllerを呼び出します。ChildViewControllerの追加と削除を確認してください:gist.github.com/tomohisa/2897676
Jakehao

@jianzong最後のステップを実行する必要がないことを覚えています。とにかく、私はそれを追加させてください、提案のためのthx。:)
Kjuly 2015

はい、それは最後のステップなしで動作します。その目的は、何かをするためにいくつかのメソッドを呼び出すようにparentViewControllerに通知することだと思います。:)
Jakehao 2015

2
(コンテナがプログラム的に表示)、私は追加しませんでした-それはイムは1つのコントローラが別のコントローラにビューを使用して、私の作品[self addChildViewController:sampleViewController];、ありがとうございました、今私はこれを追加
anjnkmr

16

問題は、適切なView Controller階層がないことだと思います。アプリのrootviewcontrollerを設定し、新しいビューコントローラーをプッシュまたは表示することで新しいビューを表示します。各View Controllerにビューを管理させます。tabbarviewcontrollerのようなコンテナービューコントローラーのみが、他のビューコントローラービューを独自のビューに追加する必要があります。ビューコントローラを適切に使用する方法の詳細については、ビューコントローラプログラミングガイドをお読みください。https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/


14

スウィフト3

これにつまずく人のために、ここに迅速な答えがあります。

self.parent?.present(viewController, animated: true, completion: nil)

9

ほぼ同じ問題があります。その理由は、「一部の」コントローラーを別のコントローラーに提示しようとしたため、アニメーションが完了した後、提示されたコントローラーをルートとして設定していたためです。この操作の後、それ以上のすべてのコントローラーを提示すると警告が表示されます:「切り離されたビューコントローラーでのビューコントローラーの提示は推奨されません」そして、私はこの警告をルートとして「一部の」コントローラーを設定するだけで解決し、最初は何も表示しません。

削除:

[[self rootController] presentViewController:controller animated:YES completion:^{

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

プレゼンテーションなしでrootとして作成します。

 [[self window] setRootViewController:controller];

1
これはまさに私の問題でした。UIModalTransitionStyleCrossDissolveでそれを提示し、それをrootViewControllerにしようとしました。その後、他のすべてのプレゼンテーションが失敗し、所定の警告メッセージが表示されました。アニメーションなしでrootViewcontrollerとして設定するだけでうまくいきました。ありがとう!
Bernardo Oliveira

7

これに対する解決策の1つは、childviewcontrollerがある場合です。したがって、与えられた

[self.parentViewController presentViewController:viewController animated:YES completion:nil];

また、dismissには同じdismissviewコントローラーを使用します。

[self dismissViewControllerAnimated:YES completion:nil];

これは完璧な解決策です。



5

このコードを試してください

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:<your ViewController object>];

[self.view.window.rootViewController presentViewController:navigationController animated:YES completion:nil];

4

TabBarControllerそれがTabBarControllerベースのアプリである場合は、プレゼンしてみてください。

[self.tabBarController presentViewController:viewController animated:YES completion:nil];

理由selfはの子でTabBarControllerあり、から提示しようとしていChildViewControllerます。


4

はい、別のビューにあるアラートコントローラを表示しているときにも、同じ警告メッセージが表示されました。後で私は、以下のように親ビューコントローラーからアラートコントローラーを提示することでこれを回避しました:

[self.parentViewController presentViewController:alertController animated:YES completion:nil];

3

新しいコントローラーを親ビューコントローラーの子として表示するビューコントローラーを追加する必要があります。

yourMainViewControllerがあり、controllerAという新しいコントローラーを追加して、controllerAからc​​ontrollerBという新しいコントローラーを表示するとします。

次のように書く必要があります:

[self addChildViewController:controllerA]; //self is yourMainViewController
[self.view addsubView:controllerA.view]; 

そしてcontrollerA内で警告なしに新しいコントローラを提示できます

[self presentViewController:controllerB animated:YES completion:nil]; //self is controllerA

3

Swift 4.1およびXcode 9.4.1の場合

解決策は

DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

このように書いた場合、同じエラーが発生します

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
    })
alert.addAction(defaultAction)

present(alert, animated: true, completion: nil) 

同じエラーが出ます

Presenting view controllers on detached view controllers is discouraged <MyAppName.ViewController: 0x7fa95560Z070>.

完全なソリューションは

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
     })
alert.addAction(defaultAction)
//Made Changes here    
DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

このようにDispatchQueueで実行すると、うまくいきました。私は、最初のビューコントローラー(最初に起動するイントロ画面で新しいユーザーを方向づける)のviewDidLoadから呼び出される、モーダルビューコントローラーに対してperformSegueを実行しています。正常に読み込まれていましたが、警告が生成されました。DispatchQueue非同期呼び出しでperformSegue呼び出しをラップすると、警告がなくなります。ありがとう!
Grant Neufeld

1

最初にルートビューコントローラーがあることを確認します。で設定できdidFinishLaunchingWithOptionsます。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [window setRootViewController:viewController];
}

1

この警告の理由はたくさんあります。私は、ViewControllerからモーダルで表示される別のセグエに接続しているセグエがあるためです。しかし、私が提示しているViewControllerは、PageViewControllerによって動的に生成されています。これが、ストーリーボードで分離されている理由です。それが原因で私のアプリがクラッシュすることはありません。しかし、私は警告を沈黙させたいと思います。


1

このスレッドで、カスタムナビゲーションバーがあり、そこからAlertViewControllerを呼び出していました。

メインのビューコントローラーに子として追加する必要がありました。それから私は何の警告もなくそれを提示することができました。

Zoomed Image View ControllerメインのViewControllerの子として追加する必要があります。

(例えば)

[self addChildViewController:ZoomedImageViewController];

その後、ZoomedImageViewControllerを呼び出すことができます。

[self presentViewController:ZoomedImageViewController];

1

多くの答えは正しいです。

  • presentingViewControllerにparentViewControllerがあるかどうかを確認します。
  • いいえの場合、追加する必要がある場所に追加します
  • それ以外の場合は、すべてのviewControllerが親になるまで、parentViewControllerにparentViewControllerがあることを再帰的に確認します

この問題は、同僚がAViewControllerをBViewControllerに追加したときに発生しました。どういうわけか、彼はAViewControllerのビューをBViewControllerのビューに追加するだけです。

追加bViewController.addChild(aViewController)で修正されました


1
ありがとうございました!Hero.shared.transition完了ブロックにaddChildを追加すると、問題が完全に解決しました。
landnbloc

0

UIViewControllerのどこにでもアラートや同様のものを表示するかどうかによって異なります。

次のコード例を使用できます。

UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Example" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil];

[alert addAction:cancelAction];


[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alert animated:true completion:nil];

あなたのコードでは、それは機能せず、このログを与えますAttempt to present <UIAlertController: 0x7fc01a1eb600> on <ViewController: 0x7fc019821e00> whose view is not in the window hierarchy!
Naveed Abbas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.