Znalazłem kilka postów dotyczących tego problemu, ale żaden z nich nie rozwiązał mojego problemu.
Powiedz, jakbym ...
- ViewControllerA
- ViewControllerB
Próbowałem dodać ViewControllerB jako widok podrzędny w ViewControllerA, ale zgłasza błąd, taki jak „ fatal error: unexpectedly found nil while unwrapping an Optional value
”.
Poniżej kod ...
ViewControllerA
var testVC: ViewControllerB = ViewControllerB();
override func viewDidLoad()
{
super.viewDidLoad()
self.testVC.view.frame = CGRectMake(0, 0, 350, 450);
self.view.addSubview(testVC.view);
// Do any additional setup after loading the view.
}
ViewControllerB to zwykły ekran z etykietą.
ViewControllerB
@IBOutlet weak var test: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
test.text = "Success" // Throws ERROR here "fatal error: unexpectedly found nil while unwrapping an Optional value"
}
EDYTOWAĆ
Z sugerowanym rozwiązaniem udzielonym przez użytkownika, ViewControllerB w ViewControllerA zniknie z ekranu. Szara ramka to ramka, którą utworzyłem dla widoku podrzędnego.
źródło
ViewControllerB
doViewControllerA
,ViewControllerB
dzieje się na ekranie. Edytowałem swój post ze zrzutem ekranu symulatora.frame
ręcznie. Lub jeśli wyłączysztranslatesFrameIntoConstraints
(lub jak to się nazywa), i prawdopodobnie możesz również programowo dodać ograniczenia. Ale jeśli dodajesz widok podrzędny, jesteś odpowiedzialny za ustawienie jego ramki w taki czy inny sposób, tak jak w przypadku wszystkich programowo dodanych widoków podrzędnych.controller.view.frame = UIScreen.mainScreen().bounds
addSubview
, widok główny kontrolera podrzędnego jest widokiem podrzędnym widoku, do którego go dodałeś. Wszystko, co musisz zrobić, to dodać ograniczenia między widokiem głównym kontrolera podrzędnego a widokiem, do którego właśnie dodałeś go jako widok podrzędny.Dzięki Rob. Dodanie szczegółowej składni do drugiej obserwacji:
let controller:MyView = self.storyboard!.instantiateViewControllerWithIdentifier("MyView") as! MyView controller.ANYPROPERTY=THEVALUE // If you want to pass value controller.view.frame = self.view.bounds self.view.addSubview(controller.view) self.addChildViewController(controller) controller.didMoveToParentViewController(self)
Aby usunąć kontroler widoku:
self.willMoveToParentViewController(nil) self.view.removeFromSuperview() self.removeFromParentViewController()
źródło
addChildViewController
, nie dzwońwillMoveToParentViewController
. DzwonienieaddChildViewController
zadzwoni za Ciebie. Zobacz Dodawanie i usuwanie dziecka w przewodniku programowania kontrolera wyświetlania dla systemu iOS. Z tego powodu osobiście zawsze dzwoniłbymaddChildViewController
natychmiast po jego utworzeniu, ale przed skonfigurowaniem.This code will work for Swift 4.2. let controller:SecondViewController = self.storyboard!.instantiateViewController(withIdentifier: "secondViewController") as! SecondViewController controller.view.frame = self.view.bounds; self.view.addSubview(controller.view) self.addChild(controller) controller.didMove(toParent: self)
źródło
willMove
.addChild
robi to za Ciebie. ZobaczwillMove
dokumentację . Zatem sekwencja to (1)addChild
; (2) skonfiguruj widok podrzędnego vc i dodaj go do hierarchii widoków; i (3) zadzwońdidMove(toParent:)
Aby dodać i usunąć ViewController
var secondViewController :SecondViewController? // Adding func add_ViewController() { let controller = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController")as! SecondViewController controller.view.frame = self.view.bounds self.view.addSubview(controller.view) self.addChild(controller) controller.didMove(toParent: self) self.secondViewController = controller } // Removing func remove_ViewController(secondViewController:SecondViewController?) { if secondViewController != nil { if self.view.subviews.contains(secondViewController!.view) { secondViewController!.view.removeFromSuperview() } } }
źródło
willMove
. Jak mówiwillMove
dokumentacja ,addChild
robi to za Ciebie.func callForMenuView () {
if(!isOpen) { isOpen = true let menuVC : MenuViewController = self.storyboard!.instantiateViewController(withIdentifier: "menu") as! MenuViewController self.view.addSubview(menuVC.view) self.addChildViewController(menuVC) menuVC.view.layoutIfNeeded() menuVC.view.frame=CGRect(x: 0 - UIScreen.main.bounds.size.width, y: 0, width: UIScreen.main.bounds.size.width-90, height: UIScreen.main.bounds.size.height); UIView.animate(withDuration: 0.3, animations: { () -> Void in menuVC.view.frame=CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width-90, height: UIScreen.main.bounds.size.height); }, completion:nil) }else if(isOpen) { isOpen = false let viewMenuBack : UIView = view.subviews.last! UIView.animate(withDuration: 0.3, animations: { () -> Void in var frameMenu : CGRect = viewMenuBack.frame frameMenu.origin.x = -1 * UIScreen.main.bounds.size.width viewMenuBack.frame = frameMenu viewMenuBack.layoutIfNeeded() viewMenuBack.backgroundColor = UIColor.clear }, completion: { (finished) -> Void in viewMenuBack.removeFromSuperview() }) }
źródło
Dzięki Robowi zaktualizowaliśmy składnię Swift 4.2
let controller:WalletView = self.storyboard!.instantiateViewController(withIdentifier: "MyView") as! WalletView controller.view.frame = self.view.bounds self.view.addSubview(controller.view) self.addChild(controller) controller.didMove(toParent: self)
źródło
willMove
. Jak mówiwillMove
dokumentacja ,addChild
robi to za Ciebie. Nie ma nic dobrego z dwukrotnego wezwania.Zapoznaj się również z oficjalną dokumentacją dotyczącą wdrażania niestandardowego kontrolera widoku kontenera:
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html#//apple_ref/doc/uid/TP40007457-CH11-SW1
Ta dokumentacja zawiera znacznie bardziej szczegółowe informacje o każdej instrukcji, a także opisuje, jak dodawać przejścia.
Przetłumaczone na Swift 3:
func cycleFromViewController(oldVC: UIViewController, newVC: UIViewController) { // Prepare the two view controllers for the change. oldVC.willMove(toParentViewController: nil) addChildViewController(newVC) // Get the start frame of the new view controller and the end frame // for the old view controller. Both rectangles are offscreen.r newVC.view.frame = view.frame.offsetBy(dx: view.frame.width, dy: 0) let endFrame = view.frame.offsetBy(dx: -view.frame.width, dy: 0) // Queue up the transition animation. self.transition(from: oldVC, to: newVC, duration: 0.25, animations: { newVC.view.frame = oldVC.view.frame oldVC.view.frame = endFrame }) { (_: Bool) in oldVC.removeFromParentViewController() newVC.didMove(toParentViewController: self) } }
źródło