Peringatan: -Menampilkan pengontrol tampilan pada pengontrol tampilan terpisah tidak disarankan

180

Di aplikasi saya, saya menggunakan pengontrol navigasi. Kemudian dalam beberapa tampilan saya menggunakan presentViewControlleruntuk menampilkan gambar yang diperbesar. Juga saya tidak menggunakan Storyboard atau nib.

Saya mendapatkan kesalahan ini hanya di iOS 7. Ini berfungsi dengan baik di iOS 6 dan sebelumnya:

Menyajikan pengontrol tampilan pada pengontrol tampilan terpisah tidak disarankan

Gagan Joshi
sumber
Saya belum tahu. Tetapi dalam aplikasi saya, saya tidak menugaskan viewcontroller ke window.rootviewcontroller. saya menambahkan tampilan ke jendela. Mungkin itulah alasan saya. tapi tidak yakin ...
Gagan Joshi
@GaganJoshi Alasan yang Anda sebutkan di atas mungkin bukan penyebabnya. Bahkan saya menghadapi masalah yang sama. Dan dalam proyek kami, saya menugaskan view controller ke window.rootviewcontroller.
Rajesh
1
Saya pikir komentar lain dengan benar menghubungkan ini dengan sesuatu tentang rootViewController dan koneksi jendela. Saya belum cukup mengetahuinya, tetapi saya dapat mengatasi masalah ini dengan menghadirkan pengontrol langsung pada rootViewController alih-alih pada pengontrol navigasi atau salah satu dari anak-anaknya.
Rich Waters
Azaxis mendapatkannya: stackoverflow.com/a/31877722/5306470
Daniel Springer

Jawaban:

207

Untuk menghindari peringatan dalam navigasi push, Anda dapat langsung menggunakan:

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

Dan kemudian di pengontrol tampilan modal Anda, ketika semuanya sudah selesai, Anda bisa memanggil:

[self dismissViewControllerAnimated:YES completion:nil];

cdescours
sumber
Saya menghadirkan pemetik gambar dengan kode baris ini "[self.view.window.rootViewController presentViewController: animasi viewController: YES completion: nil];" Tetapi tidak dapat mengabaikan tampilan poicker dengan baris ini "[self dismissViewControllerAnimated: YES completion: nil];" Opsi alternatif apa pun untuk dismisscontroller
kb920
@keyurbhalodiya Anda perlu memanggil metode dismissViewController dari modalView untuk membuatnya bekerja. Jadi jika Anda menampilkan tampilan bernama viewB dari viewA dengan [viewA.window.rootViewController presentViewController: viewB], di viewB Anda perlu menambahkan tombol misalnya, terkait dengan tindakan kustom yang memanggil [self dismissViewControllerAnimated]. Apakah ini lebih jelas?
cdescours
11
Tidak menghadirkan viewcontroller di iOS 8.
Rajesh Maurya
1
untuk iOS 8: [self.view.window.rootViewController.navigationController
Fede Cugliandolo
31
menggunakan self.navigationControllermelakukannya untuk saya.
Brandon Zacharie
62

Alasan peringatan ini adalah saya menghadirkan pengendali tampilan atas tampilan kecil yang bukan tampilan ukuran penuh. Diberikan di bawah ini adalah gambar proyek saya. di mana di klik pada empat opsi di atas. Navigasi pengguna ke tampilan childviewcontroller yang berbeda. (Berfungsi seperti tabViewcontroller). Tetapi childviewcontroller berisi tampilan ukuran kecil. Jadi, jika kami menyajikan pandangan dari childviewcontroller itu memberikan peringatan ini.

tampilan detail utama

Dan untuk menghindari ini, Anda bisa menyajikan pandangan tentang orangtua childviewcontroller

  [self.parentViewController presentViewController:viewController animated:YES completion:nil];
Gagan Joshi
sumber
1
[self.view.window.rootViewController.navigationController pushViewController: YOUR_VIEW_CONTROLER animasi: YES];
Fede Cugliandolo
1
"Mempresentasikan view controller pada tampilan kecil yang bukan tampilan ukuran penuh." ... PERSIS. Kerja bagus.
Fattie
61

Tunggu viewDidAppear() :

Kesalahan ini juga dapat muncul jika Anda mencoba menghadirkan pengontrol tampilan sebelum tampilan benar-benar muncul, misalnya menyajikan tampilan di viewWillAppear()atau sebelumnya. Cobalah untuk menyajikan tampilan lain setelah viewDidAppear()atau di dalamnya.

Azaxis
sumber
9
Dengan kata lain, jangan tampilkan pengontrol tampilan di viewDidLoad(), orang! Saya telah membuat kesalahan ini berkali-kali ...
T Blank
Terima kasih, ini membantu. Saya punya kode di viewDidLoad di mana ia mencoba menampilkan dialog di akhir.
ArdenDev
Saya mendapatkan kesalahan ini ketika menjalankan tes unit / integrasi di mana saya tidak menguji dengan animasi.
mixtly87
21

Dalam kasus saya, saya memiliki sampleViewControllerpandangan yang ditambahkan sebagai subview, kemudian mencoba menyajikan popover dari tampilan sampleViewController(di sini selfsebagai UIViewControllercontoh):

[self.view addSubview:sampleViewController.view];

Cara yang benar harus di bawah ini:

// 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];

Btw, ini juga berfungsi untuk case yang menampilkan popover dari sel tableview, Anda hanya perlu memastikan bahwa pengontrol tableview telah ditambahkan sebagai pengontrol tampilan anak.

Kjuly
sumber
Selain itu panggilan didMoveToParentViewController. Mohon lihat Tambah dan Hapus ChildViewController: gist.github.com/tomohisa/2897676
Jakehao
@ jianzong saya ingat tidak perlu melakukan langkah terakhir. Bagaimanapun, izinkan saya menambahkannya, terima kasih. :)
Kjuly
Ya itu akan berhasil tanpa langkah terakhir. Saya pikir tujuannya adalah untuk menginformasikan parentViewController sehingga akan memanggil beberapa metode untuk melakukan sesuatu. :)
Jakehao
2
ini bekerja untuk saya, saya menggunakan tampilan satu kontroler di controller lain - (Tampilan kontainer secara programatik), saya tidak menambahkan [self addChildViewController:sampleViewController];, sekarang saya menambahkan ini, terima kasih
anjnkmr
16

Saya pikir masalahnya adalah bahwa Anda tidak memiliki hierarki pengendali tampilan yang tepat. Atur rootviewcontroller aplikasi dan kemudian tampilkan tampilan baru dengan mendorong atau menghadirkan pengontrol tampilan baru pada aplikasi tersebut. Biarkan setiap pengontrol tampilan mengelola tampilan mereka. Hanya pengontrol tampilan wadah, seperti tabbarviewcontroller, yang harus menambahkan tampilan pengontrol tampilan lain ke tampilan mereka sendiri. Baca panduan pemrograman view controller untuk mempelajari lebih lanjut tentang cara menggunakan view controller dengan benar. https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/

Daniel Ytterbrink
sumber
14

Cepat 3

Bagi siapa pun yang tersandung pada ini, inilah jawaban cepatnya.

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

Saya memiliki masalah yang hampir sama. Alasannya adalah bahwa saya mencoba untuk menyajikan "beberapa" controller pada yang lain dan setelah animasi selesai saya menetapkan controller yang disajikan sebagai root. Setelah operasi ini, semua pengontrol lebih lanjut yang hadir membawa saya ke peringatan: " Menampilkan pengontrol tampilan pada pengontrol tampilan terpisah tidak disarankan ". Dan saya memecahkan peringatan ini hanya pengaturan "beberapa" controller sebagai root tanpa presentasi di awal.

Dihapus:

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

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

Jadikan sebagai root tanpa presentasi:

 [[self window] setRootViewController:controller];
averem
sumber
1
Ini persis masalah saya. Sedang berusaha menyajikannya dengan UIModalTransitionStyleCrossDissolve dan kemudian menjadikannya rootViewController. Setelah itu, semua presentasi lain gagal dengan pesan peringatan yang diberikan. Hanya mengaturnya sebagai rootViewcontroller tanpa animasi melakukan trik. Terima kasih!
Bernardo Oliveira
7

Salah satu solusi untuk ini adalah jika Anda memiliki childviewcontroller Jadi Anda cukup menampilkan viewviewcontroller pada induknya

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

Dan untuk pemberhentian menggunakan pengontrol disissview yang sama.

[self dismissViewControllerAnimated:YES completion:nil];

Ini solusi sempurna bekerja untuk saya.

Gagan Joshi
sumber
7

Gunakan [self.navigationController presentViewController:xxx animated:YES completion:nil]di iOS 8.

Tao Fang
sumber
5

Coba kode ini

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

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

Coba sajikan TabBarControllerjika ini adalah TabBarControlleraplikasi berbasis.

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

Alasan mungkin selfadalah anak dari TabBarControllerdan Anda mencoba untuk menyajikan dari ChildViewController.

Warif Akhand Rishi
sumber
4

Ya, saya juga menghadapi pesan peringatan yang sama saat menampilkan pengontrol Peringatan yang berada di tampilan lain. Kemudian saya menghindari ini dengan menghadirkan pengontrol lansiran dari pengontrol tampilan induk seperti di bawah ini:

[self.parentViewController presentViewController:alertController animated:YES completion:nil];
Sivasagar Palakurthy
sumber
3

Anda perlu menambahkan pengontrol tampilan yang akan menampilkan pengontrol baru sebagai anak dari pengontrol tampilan induk.

Katakanlah Anda memilikiMainViewController Anda, lalu Anda menambahkan controller baru yang disebut controllerA, dan kemudian Anda ingin menyajikan controller baru yang disebut controllerB dari controllerA

Anda harus menulis sesuatu seperti ini:

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

dan di dalam controllerA Anda dapat menyajikan controller baru tanpa peringatan

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

Dalam Swift 4.1 dan Xcode 9.4.1

Solusinya adalah

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

Jika menulis seperti ini saya mendapatkan kesalahan yang sama

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) 

Saya mendapatkan kesalahan yang sama

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

Solusi lengkapnya adalah

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)
})
iOS
sumber
Menjalankannya melalui DispatchQueue seperti ini bekerja untuk saya. Saya melakukan performSegue ke pengontrol tampilan modal, dipanggil dari viewDidLoad pada pengontrol tampilan pertama saya (layar intro peluncuran pertama untuk mengarahkan pengguna baru). Itu memuat baik-baik saja, tetapi menghasilkan peringatan. Membungkus panggilan performSegue di panggilan async DispatchQueue menghilangkan peringatan. Terima kasih!
Grant Neufeld
1

Pastikan Anda memiliki pengontrol tampilan root untuk memulai. Anda dapat mengaturnya didFinishLaunchingWithOptions.

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

Banyak alasan untuk peringatan ini. Milik saya karena saya memiliki segue yang terhubung dari ViewController ke yang lain yang akan disajikan secara digital. Tapi, ViewController yang saya tunjukkan sedang dihasilkan secara dinamis oleh PageViewController. Karena itulah ia terlepas di Storyboard. Aplikasi saya tidak akan macet karenanya; tapi saya ingin membungkam peringatan itu.

Lee Probert
sumber
1

Saya sampai di utas ini di mana saya memiliki Custom Navigation Bar dan saya memanggil AlertViewController melaluinya.

Saya harus menambahkannya sebagai anak ke pengendali tampilan utama saya. Lalu aku bisa memanggilnya tanpa peringatan.

Anda harus menambahkan Zoomed Image View Controller sebagai anak dari ViewController utama.

(misalnya)

[self addChildViewController:ZoomedImageViewController];

Maka Anda akan dapat memanggil ZoomedImageViewController Anda

[self presentViewController:ZoomedImageViewController];
Naveed Abbas
sumber
1

Banyak jawaban yang benar.

  • Periksa presentingViewController Anda apakah memiliki parentViewController atau tidak.
  • Jika tidak, tambahkan ke tempat yang seharusnya ditambahkan
  • selain itu, periksa apakah parentViewController memiliki parentViewController secara rekursif sampai setiap viewController memiliki orangtua

Masalah ini terjadi pada saya ketika rekan kerja saya menambahkan AViewController ke BViewController. Entah bagaimana, dia hanya menambahkan tampilan AViewController ke tampilan BViewController.

Diperbaiki dengan menambahkan bViewController.addChild (aViewController)

Jerome Li
sumber
1
Terima kasih! menambahkan addChild di blok penyelesaian Hero.share.transition saya sepenuhnya menyelesaikan masalah saya.
landnbloc
0

Itu tergantung jika Anda ingin menunjukkan peringatan Anda atau sesuatu yang serupa di mana saja dari jenis UIViewController.

Anda dapat menggunakan contoh kode ini:

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];
Fabio
sumber
Dengan kode Anda, itu tidak berfungsi dan memberikan log iniAttempt to present <UIAlertController: 0x7fc01a1eb600> on <ViewController: 0x7fc019821e00> whose view is not in the window hierarchy!
Naveed Abbas