[iOS 4주차] 문제 해결: 뒤바뀐 Main과 LaunchScreen

DoyleHWorks·2024년 11월 14일
1

배경 및 문제 파악

해당 프로젝트는 간단한 정수형 계산기 앱을 만드는 과제 프로젝트로, 본래는 UIKit 코드베이스로만 개발해서 제출해도 문제 없다.
하지만 그 전에 스토리보드로 먼저 개발해보기로 했다. 스토리보드는 초심자용 UI라고 경시하고 있었는데, 이전에 한 튜터님이 "빠르게 처리해야 하는 외주를 받는다면 스토리보드로 개발할 것이다"라고 말씀하셨던 게 떠올랐기 때문이다.

스토리보드로 기본 UI 구성

그런데 진행 도중에 문제가 발생했다.

빌드 오류
Launch screens may not contain user-defined runtime attributes.

이게 뭔 소리지?
알고보니, Main.storyboard에 작업해야 하는데 LaunchScreen.storyboard에 작업해버린 것..
혹시나 하는 마음에 LaunchScreen에서 작업한 View들을 Main에다가 옮겨보려 했지만 불가능했다.

문제 접근 및 해결 방안 A

이런 문제는 얼마나 빠른 시점에 발견하느냐가 중요하다. 현재로선 다행히 UI만 구현하고 기능은 구현하지 않았기 때문에, 프로젝트를 엎고 처음부터 새로 작성하는 게 이상적이다. 작업을 온존한 상태로 정상 궤도로 돌리기 위해 억지로 시도해볼 순 있지만, 본래 되지 않는 것을 되게 하는 것은 항상 눈에 보이지 않는 잠재적인 리스크가 따르게 되기 때문이다. 특히나 깐깐해보이는 Xcode에서는 더더욱..

첫 단추를 잘 끼우자: 프로젝트를 시작할 때는 검토, 또 검토.

문제 접근 및 해결 방안 B

하지만 한편으로는, 이런 실수를 할 기회가 드물기도 하고, 과제 마감일까지도 여유가 있기 때문에 이 상태로 Main과 Storyboard 내용을 뒤바꿔보기로 했다... 출발!!

문제 접근 1-1

가장 먼저 떠오른 방법은 Xcode를 닫은 후 폴더에서 직접 Main 파일과 LaunchScreen 파일의 이름을 서로 바꾸는 것이다.

이렇게 되어있는 파일을이렇게 수정한다

하지만 예상대로 그렇게 쉽게 굴러가진 않았다. 여전히 빌드가 되지 않는다.

문제 접근 1-2

이전에 Storyboard 파일은 XML 코드로 이루어져 있다는 것을 경험을 통해 배웠다. 각 Storyboard 파일에는 고유한 id를 비롯한 여러 속성값이 XML 형태로 저장되어 있다. 그 내용을 고치지 않는 한 해결은 불가능할 것으로 보았다.

각 storyboard 파일을 소스 코드 (XML) 형식으로 연 모습
( 파일명은 문제접근1 에서 변경한 그대로 바뀌어 있다: MainLaunchScreen )

MainStoryboard의 기본 뼈대가 어떻게 다른가 살펴보았다:

  • 초두의 <xml>은 내용이 완전히 같다.
  • <document> 부분과 <dependencies> 부분의 내용이 많이 다르다.
  • <scenes> 내용은 내가 LaunchScreen에서 작업한 내용이 들어있어서 기본 뼈대를 확실히 비교하기 어렵다.
    • <view>id값이 다르고, <rect>widthheight의 값이 다르다.
    • <viewController>id값도 다르다.

확인한 내용을 토대로 XML 코드를 수정했다.

일단 <document><dependencies> 를 제외하고 <scenes> 내용을 서로 바꾸었다.
그 다음으로는 <view>id값, <rect>widthheight의 값을 서로 바꿔주었다.

혹시 superview에 대한 constraint 설정에도 <view>id값이 들어가있는지 확인했는데, 검색에 걸리는 것은 없었다.
그리고 서로 바꿨던 MainLaunchScreen의 파일명도 되돌려주었다.
결과는..

문제 접근 1-3

기존 오류 해소 / 새로운 오류 등장:
“view controller“ is unreachable because it has no entry points,
and no identifier for runtime access via -[uistoryboard instantiateviewcontrollerwithidentifier:].

검색해보니 대부분의 결과가 해당되는 View ControllerAttributes Inspector로 가서 Is Initial View Controller에 체크를 하라고 하는데.. 잠깐, XML 코드에서 initialViewController를 본 것 같다.

initialViewController와 viewController의 id 값들을 매치되도록 Main과 storybard에서 서로 바꿔주었다
(스크린샷은 수정 과정)

결과는?

오류가 하나 줄긴 했는데..
남은 오류: Launch screens may not set custom classnames

런치스크린은 커스텀 클래스 이름을 설정할 수 없다고 한다.
잘 보니 LaunchScreen XML 코드의 <viewController> 부분이 customClass="ViewController" 속성값을 가지고 있다. 아차.. 저 내용이 포함되는 건 아까 작업해서 억지로 옮긴 <scenes> 부분이다.

새로운 접근 방법이 필요하다.

문제 접근 2

기존 뼈대를 파악하는 데 돌아가기로 했다. 대신에 이번엔 새로운 프로젝트를 생성해서 그 파일을 참조할 것이다.

새 프로젝트 생성
초기 상태의 LaunchScreenMain의 XML 코드를 살펴보자

그랬더니 상당히 신기한 점을 발견했다.
분명히 새 프로젝트를 생성했는데, LaunchScreeninitialViewController id값과 MaininitialViewController id값이 계산기 프로젝트의 것과 동일한 값이 쓰이고 있었다: BYZ-38-t0r, 01J-lp-oVM (어쩌면 같은 탬플릿에서 생성했으니 같은 id값이 초기값으로 주어지나보다). 어찌됐든 이제 완전히 초기 상태의 기본뼈대를 파악할 수 있게 되었다.

  • <xml>, <document>, <viewController> 부분이 다르다.
  • 나머지 부분은 id를 제외하고 같다.

아까 비교했을 때와는 완전히 다른 결과다.
<xml>은 같고, <depenencies>는 한 줄 차이나고 <rect>의 크기 설정조차 달랐는데..
LaunchScreen에서 작업하면서 XML 코드가 수정된건가?

초기 상태의 기본 뼈대를 기존 프로젝트에 하나씩 덮어씌웠다.

결과는?

문제 해결 및 인사이트

성공!!!

LaunchScreen에 Main 내용을 작업해버렸을 때, 해결 방법은 다음과 같다:

  • 1번 방법: 프로젝트를 엎고 새로 시작한다 (힘들지만 단순하고 안전한 방법).
  • 2번 방법: XML 코드를 열어서 서로 알맞게 바꿔 수정한다. 이 때 새 프로젝트의 기본 뼈대를 참조하면 수월하다 (어떻게든 작업을 온존하는 방법).

성공해서 기쁜 건 맞지만, 아직도 이 방법이 안전한 방법인지 잘 모르겠다. 근본적인 예방 방법은 '실수로 LaunchScreen에 작업하지 않기'이다. 그리고 실수하더라도 빠르게 파악하기 위해 '자주자주 빌드 및 실행해보기'를 실천하는 게 좋겠다. 그래도 XML 코드를 들여다보면서 독특한 트러블슈팅을 해본 건 의의가 있다고 생각한다. 처음부터 새 프로젝트를 생성해서 기본 뼈대를 비교했으면 시간 단축이 되지 않았을까 하는 생각도 든다..!

오늘도 한바탕 삽질했다 xP

profile
Reciprocity lies in knowing enough

4개의 댓글

comment-user-thumbnail
2024년 11월 14일

아 누가누가 Swift 공부 안하고 xml 전문가 될라고한다🤨!!!! 와 저는 1-3 새로운 오류 등장 쯤에 포기했을 거 같은데 결국 해내신 결말을 보고 존경심이 듭니다. 그래도 xml을 쓸 일이 언젠간 또 있을 거 같은데 그때 분명히 오늘 쌓은 이해도를 발휘하실 수 있을 거예요! 그리고 스토리보드로 작업하고 오토레이아웃 넣어보는 거 꼭 한번 이상 경험해야 한다고 생각합니다. 과제 화이팅!!!!!

1개의 답글
comment-user-thumbnail
2024년 11월 14일

감당 안되는 문제 생기면 프로젝트를 엎고 새로 시작하면 되자나? 완전 럭기빅기자나?

1개의 답글