[UIKit] storyboard없이 Navigation controller
storyboard 없이 오로지 코드만 작성하여 Navigation controller를 사용해 보자.
처음 프로젝트 생성 시 만들어지는 Main.storyboard를 과감히 지워버려도 된다 ㅎ
Navigation controller
다음과 같이 첫 화면에서 두 번째 화면으로 넘어가고 첫 화면으로 돌아올 수 있는 Navigation controller를 만들어보자.
![]() |
![]() |
ViewController | SecondViewController |
1️⃣ ViewController
import UIKit
class ViewController: UIViewController {
let label = UILabel()
let button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
initView()
// 버튼의 타겟 메서드 지정
button.addTarget(self, action: #selector(nextBtnTapped), for: .touchUpInside)
}
func initView(){
view.backgroundColor = .white
label.text = "첫 화면"
label.textAlignment = .center // 텍스트 가운데 정렬
button.setTitle("다음", for: .normal)
button.backgroundColor = .blue
// Auto Layout을 사용하여 label을 화면 중앙에 배치
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
// Auto Layout을 사용하여 button을 label 아래에 배치
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 20),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.widthAnchor.constraint(equalToConstant: 100)
])
}
@objc func nextBtnTapped(){
let secondVC = SecondViewController()
navigationController?.pushViewController(secondVC, animated: true)
}
}
2️⃣ SecondViewController
import UIKit
class SecondViewController: UIViewController {
let label = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
label.text = "두 번째 화면"
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
storyboard 삭제
Main.storyboard만 삭제한다고 되는 것이 아니다.
확인하고 싶다면 삭제하고 시뮬레이터를 실행해 보면 오류가 나는 걸 확인할 수 있을 것이다.
이제 프로젝트에서 연결된 storyboard의 싹을 다 없애버리자.
1️⃣ Project info
Project의 Info로 가서 "Main Storyboard file base name" 을 삭제해 준다.
선택하면 다음과 같이 +, - 버튼이 나오는데 - 버튼을 누르면 삭제된다.
2️⃣ info.plist
"StoryboardName"을 -버튼을 눌러 삭제해 준다.
이제 앱을 실행해 보자.
아직도 오류가 날 것이다. SceneDelegate에 설정을 해주지 않았기 때문이다.
3️⃣ SceneDelegate
이전에는 AppDelegate를 사용하여 UIWindow를 생성하고 초기화하여 앱의 화면을 관리했다.
하지만 iOS13부터 멀티 창 및 Scene환경을 지원하기 위해 AppDelegate의 역할이 변경되었고,
앱이 여러 창과 Scene을 동시에 관리할 수 있도록 SceneDelegate가 도입되었다고 한다.
- SceneDelgeate: 각각의 scene에 대한 생명주기 이벤트 처리, 각 Scene이 사용하는 Window와 ViewController 관리
따라서 iOS13 이상부터 앱이 시작될 때 AppDelegate가 아니라 "SceneDelegate"에서 초기 윈도우 설정 및 화면 구성을 담당한다.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene) // SceneDelegate의 프로퍼티에 설정해줌
let mainViewController = ViewController()
let navigationController = UINavigationController(rootViewController: mainViewController) // 네비게이션 컨트롤러 생성 및 루트 뷰 컨트롤러 설정
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}
+ navigation controller사용하지 않을 시 rootView 설정
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene) // SceneDelegate의 프로퍼티에 설정해줌
let mainViewController = ViewController()
window?.rootViewController = mainViewController
window?.makeKeyAndVisible()
}
위와 같이 storyboard 삭제하고 SceneDelegate에 코드를 작성해 주었다면 시뮬레이터를 실행해 잘 동작되는 것을 확인할 수 있다.