[iOS][Swift] - 스토리보드 없이 코드로만 UI 구현하기 (SceneDelegate에서 window설정)

llim🧚🏻‍♀️·2021년 2월 20일
9

iOS

목록 보기
3/4
post-thumbnail

안녕하세요. 엘림입니다🙇🏻‍♀️

오늘은 스토리보드 없이, 코드로만 UI를 구현하기 위해서 info.plist와 SceneDelegate를 설정하는 방법에 대해 알아보겠습니다.

이 글은 공부하면서 작성한 글이기 때문에 잘못된 정보가 있을 수 있습니다.🥺
금방 잊어버릴... 미래의 저에게 다시 알려주기 위한 글이다보니
혹시라도 틀린 부분이 있다면, 댓글로 친절하게 알려주시길 부탁드립니다.🙏


그럼 시작해봅시다!

Main.storyboard 삭제

실습(?)을 위해서 withoutStoryboard라는 프로젝트를 생성해주었습니다. 그 후 필요 없어진😱 Main.storyboard를 Move To Trash하여 쓰레기통🚮에 버려 주었습니다.

자, 이제 끝났네요. 빌드를 하면 화면이 잘 나올거에요. 라고 생각한 사람 정말 저뿐인가요? 그냥 지워도 잘 돌아갈 줄 알았는데, 빌드를 해보니... 런타임 에러가 두둥!!

Thread 1: "Could not find a storyboard named 'Main' in bundle NSBundle </Users/llim/Library/Developer/CoreSimulator/Devices/9A4569B2-0E95-46BF-9498-3D3E72DB5D7F/data/Containers/Bundle/Application/E57ED200-8C26-497E-BF80-7FCBDEBEC785/withoutStroyboard.app> (loaded)"

네..? 뭐라고요..? 복잡해 보이지만, 맨 윗줄만 살펴보자면
Could not find a storyboard named 'Main'

'Main'이라는 스토리 보드를 찾을 수 없습니다.

라고 나오네요!
제가 설정한 것은 아니지만, 프로젝트를 생성할때 자동으로 Main.storyborad를 만들면서 무엇인가 설정된 것 같아요.
그래서 저는 info.plist로 향합니다.

info.plist 설정

❗️제가 가끔, test에 info.plist로 간적이있는데요ㅠㅠ. 여러분들은 꼭꼭 여러개의 info.plist중에 test와 관련없는!! 메인(?) info.plist로 가주세요!

지금 캡쳐에는 제가 > 화살표를 눌러서 열어놨지만, 여러분의 Application Scene Manifest는 닫혀있을거에요!
>를 눌러서 열고, Scene Configuration을 또 열고, 열고 열고~~ 하다보면 Storyboard Name을 만날 수 있습니다!
여기서 저 Main을 지워주면 되는데요.
꼭꼭 왼쪽에 -버튼을 눌러서 완전히 삭제해주세요!
오른쪽에 Main이라는 단어만 지우면 Thread 1: "Invalid parameter not satisfying: [name length] > 0"라는 에러를 만나게 되거든요^^^^^
꼭꼭 -버튼을 눌러서 Storyboard Name 칸 자체를 지워주세요!

자, 이제는 됐겠지 싶어서 제가 또 빌드를 해봤어요. 어떤가요?

마치, 제 미래처럼 어둡네요. 왜.. 시뮬레이터 화면이 검은색일까요?

사실 스토리보드를 사용했을때에도 이 Is Initial View Controller가 설정 안되어있을때 이런 화면을 본적이 있답니다!
아니 그런데, 우리는 지금 스토리보드가 없잖아요.😱
자, 그럼 어디를 설정해야할까요?

SceneDelegate 설정

‼️ 아래 내용은 iOS Target 13 이상인 경우를 중심으로 서술되어있습니다. 그 이유는 iOS 13부터 AppDelegate의 UI Lifecycle의 역할을 SceneDelegate에게 넘겨주어, Scene 즉 화면과 관련된 부분을 SceneDelegate가 담당하게 되었기 때문입니다. 관련 자료. AppDelegate에서 작업하는 부분도 추가적으로 서술되어있으나, 부족할 수 있는 점 양해부탁드립니다.🙏

자, 이렇게 SceneDelegate에 오면, 15번째 줄에 scene이라는 메서드를 볼 수 있습니다. 이 안에다가 내용을 채워줄텐데요.

(iOS 13버전 미만 타겟에서는, AppDelegate의 func application(- application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 메서드 내부에 작업해주세요!)

기존에 guard let _ = (scene as? UIWindowScene) else { return } 변수에 이름을 지어줍니다. 저는 windowScene로 해볼게요.

guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene) // SceneDelegate의 프로퍼티에 설정해줌
let mainViewController = ViewController() // 맨 처음 보여줄 ViewController

window?.rootViewController = mainViewController
window?.makeKeyAndVisible()

이름을 만들어준 그 UIWindowScene을 SceneDelegate의 window 프로퍼티에 대입해줍니다.

그 다음 rootViewController에 넣어줄 컨트롤러를 만들어줍니다.
이때 rootViewController에 넣어주는 컨트롤러가, 스토리보드에서 Is Initial View Controller로 설정해주는 컨트롤러라고 생각하시면 좋을거같습니다.

그 후에 makeKeyAndVisible()를 window에 설정해주면 짜잔~ 하고 화면이 나오는 것을 확인할 수 있습니다!


ps. 필요없는 주석은 지워버리자고요🥴

다 따라하고 빌드를 했는데, 여전히 까만화면이라고요?!!
ㅎㅎㅎㅎ... 그럴 수 있어요.

확인해보기

놀랍게도 여러분.. 제가 요즘 UI를 코드로 짜보니까 알게되었는데요. UIViewController들이 배경색이 시커멓더라고요....
그래서 viewDidLoad에 배경색과, 확인을 위한 라벨을 넣어봅시다.

let test = UILabel()
view.backgroundColor = .white // 배경색
view.addSubview(test)
test.text = "text" // test를 위해서 출력할 라벨 
test.translatesAutoresizingMaskIntoConstraints = false
test.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
test.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

(혹시 상단의 코드가 이해 안간다면, 코드로 UI 구현하기 part.1을 참고해주세요.)

감동적이네요😻

아, 그런데 그 첫 화면부터 혹시라도 navigaitonCotroller가 필요하다고요?
그러면 약간의 설정을 더 추가해줘야해요!

지금까지 위에서 작업한 화면이, 스토리보드로 따지면 이렇게 viewController자체가 첫 화면으로 되어있는건데요.
navigation controller가 있는 view를 첫 화면으로 하면 아래처럼 되겠죠?


바로 viewController가 아니라, navigationController가 시작점이고, 거기에 담겨(?)있는 viewController를 저희가 보게 되는거죠!

설명은 여기까지, 그렇다면 코드로 한번 볼게요!
위에서 작성한 코드에서,

 guard let windowScene = (scene as? UIWindowScene) else { return }
 window = UIWindow(windowScene: windowScene) 
 
 let mainViewController = ViewController() // 이 뷰컨트롤러를 내비게이션 컨트롤러에 담아볼게요!
 
 let navigationController = UINavigationController(rootViewController: mainViewController) // 내비게이션 컨트롤러에 처음으로 보여질 화면을 rootView로 지정해주고!
        
window?.rootViewController = navigationController // 시작을 위에서 만든 내비게이션 컨트롤러로 해주면 끝!
window?.makeKeyAndVisible()

위에 코드에서 주석으로 설명한 것 처럼, 처음 보여질 화면을 내비게이션 컨트롤러의 root로 설정해준뒤, window에 root를 내비게이션 컨트롤러로하면 끝입니다!
생각보다 간단하죠?

내용은 없지만, 내비게이션 바가 보이네요😻

여기까지 따라오시느라 고생하셨습니답!

오늘의 포스팅 마무리하겠습니다.




잘못된 것이 있거나, 궁금한 것이 있다면 언제든지 댓글✍🏻이나 메일📬 주세요오🙇🏻‍♀️



참고 링크👍👍👍
makeKeyAndVisible
https://developer.apple.com/documentation/uikit/uiwindow/1621601-makekeyandvisible
[Swift] Xcode11 - Main Storyboard 없이 프로젝트 시작하기
https://developer-fury.tistory.com/41
[Swift] UISplitViewController Tutorial (스플릿뷰 기본 사용기)
https://m.blog.naver.com/PostView.nhn?blogId=xodhks_0113&logNo=221071131409&proxyReferer=https:%2F%2Fwww.google.com%2F

profile
한달 차 iOS 개발자입니다🐥

1개의 댓글

comment-user-thumbnail
2021년 9월 1일

엘림! 안녕하세요! 엘렌이예요 :)
plist에서 Application Scene Manifes안의 Storyboard Name만 지웠을때 문제가 생겨서 찾아보니
Main Storyboard file base name도 삭제하니 잘 되었습니다!
제가 글을 제대로 읽지 않은것인지 이 부분에 대해서는 나와있지 않는 것 같아서 댓글 남겼습니다!!
코드로 UI 구현하기 시리즈 잘 보고있습니다 감사합니다! ㅎㅎㅎ

답글 달기