- 로그인 화면 AutoLayout 적용하기
- 회원가입 화면 AutoLayout 적용하기
- 확인 화면 AutoLayout 적용하기
- 확인 화면에 "다른 계정으로 로그인하기" 버튼 추가하기
- 확인 화면에 "다른 계정으로 로그인하기 버튼 추가" 누르면 처음 로그인 화면으로 돌아가기
- 확인 화면에서 확인 화면 누르면 Tabbar로 연결된 화면 Present 하기
- Tabbar에 5개의 view controller 연결하기
- tabbar title, image, selected image 바꾸기
- Tabbar 화면 구성하기
- 확인 버튼 누를 시, 탭바 화면으로 이동
@IBAction func confirmButton(_ sender: Any) {
let tabBarStoryboard = UIStoryboard.init(name: "TabBar", bundle: nil)
guard let tabbar = tabBarStoryboard.instantiateViewController(withIdentifier: "TabBarController") as? TabBarController else {return}
tabbar.modalPresentationStyle = .fullScreen
tabbar.modalTransitionStyle = .crossDissolve
present(tabbar, animated: true, completion: nil)
}
@IBAction func otherLoginButtonDidTap(_ sender: Any) {
guard let naviVC = self.storyboard?.instantiateViewController(withIdentifier: "NavigationController")
as? NavigationController else {return}
naviVC.modalPresentationStyle = .fullScreen
naviVC.modalTransitionStyle = .crossDissolve
self.present(naviVC, animated: true, completion: nil)
}
→ 다른 계정으로 로그인 하기 버튼을 누를 경우, navigation controller를 가져와 naviVC에 저장한뒤, 모달로 다시 띄워주는 방식 ! ( fullscreen으로 , 효과는 crossdissolve )
→ 단순히 로그인 화면 으로 돌아가면 다음 화면인 회원가입 창이 켜지지 않음 ! 스택이 쌓이지 않음 ..!!
→ 네비게이션 컨트롤러로 돌아가야 로그인 창부터 회원가입 창 까지 스택이 쌓임 !!
더 찾아보니 UINavigationController 클래스의 메서드 중에 popToRootViewController를 통해 루트 뷰 컨트롤러까지 pop할 수 있었음 ! 하지만, 문제는 present로 띄운 모달창을 없애야 pop이 정상적으로 작동 된다는 것!
-
첫 번째 시도
self.navigationController?.popToRootViewController(animated: false)
이렇게만 해주면 작동이 안됨..
-
두 번째 시도
self.dismiss(animated: true) { self.navigationController?.popToRootViewController(animated: true) }
두 번째로 시도한건 dissmiss 해주면서 루트 뷰 컨트롤러로 바로 돌아가게 해주는 것 !
근데 이것도 제대로 작동을 하지 않았음 ! 그래서 코드리뷰하면서 오비 선배림들한테 여쭤봄 .!
애플 공식 문서 참고 !
📌 루트뷰로 돌아가기 위해서 popToRootViewController(animated:)
메서드를 시도했을거라고 생각해요!dismiss 하게되면 현재 뷰가 메모리 상에서 사라집니다. 그래서 아래의 코드를 사용하면 이미 사라진 현재뷰의 navigationController 를 참조하게 되는 꼴이되죠! 아마 여기를 놓쳤을 것 같아요
self.dismiss(animated: true) {
self.navigationController?.popViewController(animated: true)
}
그래서 guard let presentingVC = self.presentingViewController else { return }
이렇게 현재 뷰컨트롤러를 제공한 뷰컨트롤러 객체를 가져와서 presentingVC 를 대상으로 pop 시켜줘야 한답니다!
guard let presentingVC = self.presentingViewController as? UINavigationController else { return }
dismiss(animated: true) {
presentingVC.popToRootViewController(animated: true)
}
결론 ? dissmiss 하는 순간 현재 뷰가 메모리에서 사라지기 때문에 ! 현재 뷰를 다시 가져와서 그 뷰에서 루트 뷰 컨트롤러로 pop해줘야된다
-> 수정 : 현재 뷰가 메모리에서 사라지기 때문에 self.navigationController?
가 비어있어요. 그리고 애초에 present 로 뷰가 화면전환되었기 때문에 viewDidLoad() 에서 출력해보셔도 비어있습니다! push 로 화면전환을 한 것이 아니기 때문이죠! 그래서 이 부분은 dismiss 하면 메모리에서 뷰가 해제되는데 self.
로 접근할 수 있는 것이 없다! 라고 생각하시면 될거같아요👍
@IBAction func otherLoginButtonDidTap(_ sender: Any) {
guard let presentingVC = self.presentingViewController as? UINavigationController else { return }
self.dismiss(animated: true) {
presentingVC.popToRootViewController(animated: true)
}
}