다른 뷰 컨트롤러에서 뷰 컨트롤러를 하위 뷰로 추가
이 문제에 대한 게시물을 거의 찾았지만 아무도 내 문제를 해결하지 못했습니다.
내가 ..
- ViewControllerA
- ViewControllerB
ViewControllerA에서 ViewControllerB를 하위보기로 추가하려고했지만 " fatal error: unexpectedly found nil while unwrapping an Optional value" 와 같은 오류가 발생 합니다.
아래는 코드입니다 ...
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는 레이블이있는 단순한 화면입니다.
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"
}
편집하다
사용자 답변의 제안 된 솔루션으로 ViewControllerA의 ViewControllerB가 화면에서 사라집니다. 회색 테두리는 하위보기 용으로 만든 프레임입니다.
몇 가지 관찰 :
두 번째 뷰 컨트롤러를 인스턴스화 할 때
ViewControllerB(). 해당 뷰 컨트롤러가 프로그래밍 방식으로 뷰를 생성하면 (비정상적 임) 괜찮을 것입니다. 그러나의 존재는IBOutlet이 두 번째 뷰 컨트롤러의 장면이 Interface Builder에 정의되어 있음을 시사하지만를 호출ViewControllerB()하면 스토리 보드에 해당 장면을 인스턴스화하고 모든 콘센트를 연결할 수있는 기회를주지 않습니다. 따라서 암시 적으로 래핑되지 않은UILabel것은nil이므로 오류 메시지가 나타납니다.대신 인터페이스 빌더에서 대상 뷰 컨트롤러에 "스토리 보드 ID"를 제공하고
instantiateViewController(withIdentifier:)이를 인스턴스화하는 데 사용할 수 있습니다 (그리고 모든 IB 아웃렛을 연결). Swift 3 :let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")이제이 액세스 할 수있는
controller'들view.그러나 정말로하고 싶다면
addSubview(즉, 다음 장면으로 전환하지 않는 경우) "뷰 컨트롤러 격리"라는 연습에 참여하는 것입니다. 당신은 단순히 원하는 것이 아닙니다addSubview. 몇 가지 추가 컨테이너 뷰 컨트롤러 호출을 수행하려고합니다. 예 :let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id") addChild(controller) controller.view.frame = ... // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview view.addSubview(controller.view) controller.didMove(toParent: self)더이는 이유에 대한 자세한 내용은
addChild(이전에 호출addChildViewController) 및didMove(toParent:)(이전이라고didMove(toParentViewController:)) 필요, 참조 구현의 UIViewController 봉쇄 - WWDC 2011 비디오 # 102 . 요컨대, 뷰 컨트롤러 계층이 뷰 계층과 동기화되어 있는지 확인해야 하며 이러한 호출이addChild이에 해당didMove(toParent:)하는지 확인해야합니다.View Controller Programming Guide 의 Creating Custom Container View Controllers 도 참조하십시오 .
그런데 위의 내용은 프로그래밍 방식으로 수행하는 방법을 보여줍니다. Interface Builder에서 "컨테이너 뷰"를 사용하면 실제로 훨씬 더 쉽습니다.

그러면 이러한 포함 관련 호출에 대해 걱정할 필요가 없으며 Interface Builder가 처리해줍니다.
Swift 2 구현 의 경우이 답변의 이전 개정판을 참조하십시오 .
Rob에게 감사합니다. 두 번째 관찰에 대한 자세한 구문 추가 :
let controller:MyView = self.storyboard!.instantiateViewControllerWithIdentifier("MyView") as! MyView
controller.ANYPROPERTY=THEVALUE // If you want to pass value
controller.view.frame = self.view.bounds;
controller.willMoveToParentViewController(self)
self.view.addSubview(controller.view)
self.addChildViewController(controller)
controller.didMoveToParentViewController(self)
그리고 viewcontroller를 제거하려면 :
self.willMoveToParentViewController(nil)
self.view.removeFromSuperview()
self.removeFromParentViewController()
This code will work for Swift 4.2.
let controller:SecondViewController =
self.storyboard!.instantiateViewController(withIdentifier: "secondViewController") as!
SecondViewController
controller.view.frame = self.view.bounds;
controller.willMove(toParent: self)
self.view.addSubview(controller.view)
self.addChild(controller)
controller.didMove(toParent: self)
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()
})
}
Rob 덕분에 Swift 4.2 구문 업데이트
let controller:WalletView = self.storyboard!.instantiateViewController(withIdentifier: "MyView") as! WalletView
controller.view.frame = self.view.bounds;
controller.willMove(toParent: self)
self.view.addSubview(controller.view)
self.addChild(controller)
controller.didMove(toParent: self)
커스텀 컨테이너 뷰 컨트롤러 구현에 대한 공식 문서도 확인하세요.
이 문서는 모든 지침에 대해 훨씬 더 자세한 정보를 제공하며 전환을 추가하는 방법도 설명합니다.
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)
}
}
ViewController 추가 및 제거
var secondViewController :SecondViewController?
// Adding
func add_ViewController() {
let controller = self.storyboard?.instantiateViewController(withIdentifier: "secondViewController")as! SecondViewController
controller.view.frame = self.view.bounds;
controller.willMove(toParent: self)
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()
}
}
}
'Program Tip' 카테고리의 다른 글
| ScrollView 내의 이미지 그리드 (0) | 2020.11.22 |
|---|---|
| @Override를 사용하여 "수퍼 클래스 메서드를 재정의해야 함"이 표시되는 이유는 무엇입니까? (0) | 2020.11.22 |
| Eclipse에 오류가 표시되지만 찾을 수 없습니다. (0) | 2020.11.22 |
| 데이터베이스에 대한 CREATE 스크립트 내보내기 (0) | 2020.11.22 |
| 뷰가 애니메이션 된 후 setVisibility가 작동하지 않는 이유는 무엇입니까? (0) | 2020.11.22 |