คำเตือน: - การนำเสนอตัวควบคุมมุมมองบนตัวควบคุมมุมมองที่แยกออกมานั้นไม่สนับสนุน


180

ในแอพของฉันฉันใช้ตัวควบคุมทิศทาง ต่อมาในบางมุมมองฉันใช้presentViewControllerเพื่อแสดงภาพซูม นอกจากนี้ฉันไม่ได้ใช้สตอรีบอร์ดหรือปลายปากกา

ฉันได้รับข้อผิดพลาดนี้ใน iOS 7 เท่านั้น ทำงานได้ดีใน iOS 6 และรุ่นก่อนหน้า:

การนำเสนอตัวควบคุมมุมมองบนตัวควบคุมมุมมองที่แยกออกมานั้นไม่สนับสนุน


ฉันยังไม่ได้คิดออก แต่ในแอพของฉันฉันไม่ได้กำหนดวิวเวอร์ให้กับ window.rootviewcontroller ฉันกำลังเพิ่มมุมมองในหน้าต่าง อาจเป็นเหตุผลที่ฉัน แต่ไม่แน่ใจ ...
Gagan Joshi

@GaganJoshi เหตุผลที่คุณกล่าวถึงข้างต้นอาจไม่ใช่สาเหตุ แม้ฉันกำลังเผชิญปัญหาเดียวกัน และในโครงการของเราฉันกำลังกำหนดตัวควบคุมมุมมองให้กับ window.rootviewcontroller
Rajesh

1
ฉันคิดว่าความคิดเห็นอื่น ๆ ที่เกี่ยวข้องนี้เกี่ยวข้องกับบางอย่างเกี่ยวกับ rootViewController และการเชื่อมต่อหน้าต่าง ฉันไม่ได้คิดมาก่อน แต่ฉันสามารถแก้ไขปัญหาได้โดยการนำเสนอตัวควบคุมโดยตรงบน rootViewController แทนที่จะเป็นตัวควบคุมการนำทางหรือลูก ๆ ของมัน
Rich Waters

คำตอบ:


207

เพื่อหลีกเลี่ยงการได้รับคำเตือนในการนำทางแบบพุชคุณสามารถใช้:

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

จากนั้นในตัวควบคุมมุมมอง modal ของคุณเมื่อทุกอย่างเสร็จสิ้นคุณสามารถโทร:

[self dismissViewControllerAnimated:YES completion:nil];


ฉันกำลังนำเสนอเครื่องมือเลือกรูปภาพด้วยรหัสบรรทัดนี้ "[self.view.window.rootViewController presentViewController: viewController เคลื่อนไหว: เสร็จสิ้นใช่: ไม่มี];" แต่ไม่สามารถยกเลิกมุมมอง poicker ด้วยบรรทัดนี้ "[self dismissViewControllerAnimated: YES complete: nil];" ตัวเลือกอื่น ๆ สำหรับ dismisscontroller
kb920

@keyurbhalodiya คุณต้องเรียกใช้เมธอด dismissViewController จาก modalView เพื่อให้ทำงานได้ ดังนั้นถ้าคุณแสดงมุมมองชื่อ viewB จาก viewA ด้วย [viewA.window.rootViewController presentViewController: viewB] ใน viewB คุณต้องเพิ่มปุ่มตัวอย่างเช่นเชื่อมโยงกับแอ็คชันแบบกำหนดเองที่เรียกใช้ [self dismissViewControllerAnimated] ชัดเจนหรือไม่
cdescours

11
ไม่แสดงตัวควบคุมการดูใน iOS 8
Rajesh Maurya

1
สำหรับ iOS 8: [self.view.window.rootViewController.navigationController
Fede Cugliandolo

31
ใช้self.navigationControllerมันสำหรับฉัน
แบรนดอน Zacharie

62

เหตุผลของคำเตือนนี้คือฉันกำลังแสดงตัวควบคุมมุมมองผ่านมุมมองขนาดเล็กที่ไม่ใช่มุมมองขนาดเต็ม รับด้านล่างเป็นภาพของโครงการของฉัน ที่คลิกสี่ตัวเลือกด้านบน ผู้ใช้นำทางไปยังมุมมองที่แตกต่างกันของ childviewcontroller (ทำงานเหมือนกับ tabViewcontroller) แต่ตัวควบคุม childview มีมุมมองขนาดเล็ก ดังนั้นหากเรานำเสนอมุมมองจาก childviewcontroller จะให้คำเตือนนี้

มุมมองรายละเอียดหลัก

และเพื่อหลีกเลี่ยงปัญหานี้คุณสามารถแสดงมุมมองบนพาเรนต์ของ childviewcontroller

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

1
[self.view.window.rootViewController.navigationController pushViewController: YOUR_VIEW_CONTROLER เคลื่อนไหว: ใช่];
Fede Cugliandolo

1
"กำลังเสนอตัวควบคุมมุมมองผ่านมุมมองขนาดเล็กที่ไม่ใช่มุมมองขนาดเต็ม" ... แน่นอน ทำได้ดีมาก
Fattie

61

รอviewDidAppear():

ข้อผิดพลาดนี้ยังสามารถเกิดขึ้นได้หากคุณพยายามที่จะนำเสนอมุมมองตัวควบคุมก่อนที่จะดูมุมมองที่เกิดขึ้นจริงเช่นนำเสนอมุมมองในviewWillAppear()หรือก่อนหน้า ลองนำเสนอมุมมองอื่นหลังจากviewDidAppear()หรือภายในมุมมองนั้น


9
กล่าวอีกนัยหนึ่งไม่แสดงตัวควบคุมมุมมองใด ๆviewDidLoad()ผู้คน! ผมได้ทำผิดพลาดนี้ดังนั้นหลายครั้ง ...
T Blank

ขอบคุณสิ่งนี้ช่วย ฉันมีรหัสใน viewDidLoad ที่พยายามแสดงข้อความโต้ตอบท้ายที่สุด
ArdenDev

ฉันได้รับข้อผิดพลาดนี้เมื่อเรียกใช้การทดสอบหน่วย / การรวมที่ฉันไม่ได้ทดสอบด้วยภาพเคลื่อนไหว
mixtly87

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

Btw, มันยังใช้ได้กับกรณีที่มี popover ในรูปแบบเซลล์ tableview, คุณเพียงแค่ต้องแน่ใจว่าตัวควบคุม tableview นั้นถูกเพิ่มเข้าไปเป็นตัวควบคุม child view ด้วย


นอกจากนี้การเรียก didMoveToParentViewController คำตอบตรวจสอบเพิ่มและลบ ChildViewController: gist.github.com/tomohisa/2897676
Jakehao

@jianzong ฉันจำได้ว่าไม่จำเป็นต้องทำขั้นตอนสุดท้าย วิธีใดให้ฉันเพิ่มขอบคุณสำหรับคำแนะนำ :)
Kjuly

ใช่มันจะทำงานโดยไม่มีขั้นตอนสุดท้าย ฉันคิดว่ามันมีจุดประสงค์เพื่อแจ้ง parentViewController เพื่อให้มันเรียกวิธีการบางอย่าง :)
Jakehao

2
มันใช้งานได้สำหรับฉันฉันใช้มุมมองตัวควบคุมหนึ่งในตัวควบคุมอื่น - (มุมมองคอนเทนเนอร์โดยทางโปรแกรม) ฉันไม่ได้เพิ่ม[self addChildViewController:sampleViewController];ตอนนี้ฉันเพิ่มสิ่งนี้แล้วขอขอบคุณ
anjnkmr

16

ฉันคิดว่าปัญหาคือคุณไม่มีลำดับชั้นของตัวควบคุมมุมมองที่เหมาะสม ตั้งค่า rootviewcontroller ของแอพแล้วแสดงมุมมองใหม่โดยการกดหรือนำเสนอตัวควบคุมมุมมองใหม่ ให้ตัวควบคุมมุมมองแต่ละตัวจัดการมุมมองของพวกเขา เฉพาะตัวควบคุมมุมมองคอนเทนเนอร์เช่น 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

หนึ่งในวิธีการแก้ปัญหานี้คือถ้าคุณมี childviewcontroller ดังนั้นคุณเพียงแค่นำเสนอ viewview บน parent โดยกำหนด

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

และสำหรับการยกเลิกให้ใช้ตัวควบคุม 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เป็นลูกของคุณและคุณกำลังพยายามที่จะนำเสนอจากTabBarControllerChildViewController


4

ใช่ฉันยังต้องเผชิญกับข้อความเตือนเดียวกันในขณะที่แสดงตัวควบคุมการแจ้งเตือนซึ่งอยู่ในมุมมองอื่น ในภายหลังฉันหลีกเลี่ยงสิ่งนี้โดยนำเสนอตัวควบคุมการแจ้งเตือนจากตัวควบคุมมุมมองหลักดังต่อไปนี้:

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

3

คุณต้องเพิ่มตัวควบคุมมุมมองที่จะนำเสนอตัวควบคุมใหม่เป็นลูกของตัวควบคุมมุมมองหลัก

สมมติว่าคุณมีเมนวิวคอนโทรลเลอร์ของคุณจากนั้นคุณเพิ่มคอนโทรลเลอร์ใหม่ที่เรียกว่าคอนโทรลเลอร์ A จากนั้นคุณต้องการนำเสนอคอนโทรลเลอร์ใหม่ที่ชื่อว่าคอนโทรลเลอร์Bจากคอนโทรลเลอร์ A

คุณต้องเขียนอะไรแบบนี้:

[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 แบบนี้ใช้ได้กับฉัน ฉันกำลังทำ performSegue ให้กับตัวควบคุมมุมมอง modal เรียกจาก viewDidLoad บนตัวควบคุมมุมมองแรกของฉัน (หน้าจอเริ่มต้นที่เปิดใช้งานครั้งแรกเพื่อปรับทิศทางผู้ใช้ใหม่) มันโหลดได้ดี แต่สร้างคำเตือน การตัดการเรียกใช้ PerformSegue ในการเรียกใช้ DispatchQueue async จะเป็นการกำจัดคำเตือน ขอบคุณ!
Grant Neufeld

1

ตรวจสอบให้แน่ใจว่าคุณมีตัวควบคุมรูทวิวเพื่อเริ่มต้น didFinishLaunchingWithOptionsคุณสามารถตั้งค่าใน

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

1

มีเหตุผลมากมายสำหรับการเตือนนี้ Mine เป็นเพราะฉันมีส่วนต่อเชื่อมจาก ViewController ไปยังอีกอันหนึ่งที่จะถูกนำเสนออย่างสุภาพ แต่ ViewController ที่ฉันกำลังนำเสนอจะถูกสร้างขึ้นแบบไดนามิกโดย PageViewController นี่คือเหตุผลว่าทำไมจึงถูกถอดออกในกระดานเรื่องราว แอพของฉันจะไม่พังเพราะมัน; แต่ฉันต้องการที่จะเงียบคำเตือน


1

ฉันไปถึงหัวข้อนี้ที่ฉันมี Custom Navigation Bar และฉันเรียก AlertViewController

ฉันต้องเพิ่มมันเป็นเด็กไปยังตัวควบคุมมุมมองหลักของฉัน จากนั้นฉันก็สามารถโทรหาพวกเขาได้โดยไม่มีการเตือนล่วงหน้า

คุณควรเพิ่มคุณZoomed Image View Controllerเป็นลูกของ ViewController หลัก

(เช่น)

[self addChildViewController:ZoomedImageViewController];

จากนั้นคุณจะสามารถเรียก ZoomedImageViewController ของคุณ

[self presentViewController:ZoomedImageViewController];

1

คำตอบมากมายถูกต้อง

  • ตรวจสอบ presentingViewController ของคุณว่ามี parentViewController หรือไม่
  • หากไม่มีให้เพิ่มไปยังที่ที่ควรเพิ่ม
  • มิฉะนั้นตรวจสอบมัน parentViewController มี parentViewController ซ้ำจนกว่า viewController ทุกคนมีผู้ปกครอง

ปัญหานี้เกิดขึ้นกับฉันเมื่อเพื่อนร่วมงานของฉันเพิ่ม AViewController ใน BViewController อย่างใดเขาเพียงเพิ่มมุมมองของ AViewController ในมุมมองของ BViewController

แก้ไขโดยเพิ่ม bViewController.addChild (aViewController)


1
ขอบคุณ! การเพิ่ม addChild ใน Hero.shared.transition complete block ของฉันแก้ปัญหาของฉันได้อย่างสมบูรณ์
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.