다른 뷰 컨트롤러에서 뷰 컨트롤러를 하위 뷰로 추가
이 문제에 대한 게시물을 거의 찾았지만 아무도 내 문제를 해결하지 못했습니다.
내가 ..
- 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 |