โดยทั่วไประบบควรจัดการอินสแตนซ์ตัวควบคุมมุมมองด้วยสตอรีบอร์ด สิ่งที่คุณต้องการคือการสำรวจลำดับชั้นของ viewController โดยใช้การอ้างอิงไปยังสิ่งself.window.rootViewController
ที่ตรงข้ามกับการเริ่มต้นตัวควบคุมมุมมองซึ่งควรเริ่มต้นอย่างถูกต้องหากคุณตั้งค่าสตอรี่บอร์ดอย่างถูกต้อง
สมมติว่าคุณrootViewController
เป็น UINavigationController จากนั้นคุณต้องการส่งบางอย่างไปยังตัวควบคุมมุมมองด้านบนคุณจะทำเช่นนี้ใน AppDelegate ของคุณdidFinishLaunchingWithOptions
:
UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;
ใน Swift ถ้าจะคล้ายกันมาก:
let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data
คุณไม่ควรเริ่มต้นตัวควบคุมมุมมองโดยใช้รหัสสตอรี่บอร์ดจากตัวแทนของแอปเว้นแต่คุณต้องการข้ามวิธีโหลดสตอรีบอร์ดปกติและโหลดสตอรีบอร์ดทั้งหมดด้วยตัวเอง หากคุณต้องเริ่มต้นฉากจาก AppDelegate คุณมักจะทำอะไรผิดพลาด ฉันหมายถึงลองนึกดูว่าคุณต้องการส่งข้อมูลไปยังตัวควบคุมมุมมองทางลงสแต็กด้วยเหตุผลบางประการ AppDelegate ไม่ควรเข้าไปในสแต็กคอนโทรลเลอร์มุมมองเพื่อตั้งค่าข้อมูล นั่นไม่ใช่ธุรกิจของมัน มันเป็นธุรกิจคือ rootViewController ปล่อยให้ rootViewController จัดการลูก ๆ ของมันเอง! ดังนั้นถ้าฉันข้ามขั้นตอนการโหลดสตอรี่บอร์ดตามปกติโดยระบบโดยลบการอ้างอิงไปยังไฟล์ info.plist ฉันจะสร้างอินสแตนซ์ rootViewController โดยใช้instantiateViewControllerWithIdentifier:
และอาจเป็นรูทถ้าเป็นคอนเทนเนอร์เช่น UINavigationController สิ่งที่คุณต้องการหลีกเลี่ยงคือการสร้างอินสแตนซ์ตัวควบคุมมุมมองที่ได้รับการสร้างอินสแตนซ์โดยสตอรี่บอร์ดแล้ว นี่เป็นปัญหาที่ฉันเห็นมาก ในระยะสั้นฉันไม่เห็นด้วยกับคำตอบที่ยอมรับ มันไม่ถูกต้องเว้นแต่ผู้โพสต์จะหมายถึงการลบการโหลดสตอรีบอร์ดออกจาก info.plist เนื่องจากคุณจะโหลดสตอรีบอร์ด 2 รายการเป็นอย่างอื่นซึ่งไม่สมเหตุสมผล อาจไม่ใช่หน่วยความจำรั่วเนื่องจากระบบเริ่มต้นฉากรูทและกำหนดให้กับหน้าต่าง แต่จากนั้นคุณก็เข้ามาและสร้างอินสแตนซ์อีกครั้งและกำหนดอีกครั้ง แอปของคุณเริ่มต้นได้ไม่ดีนัก!