해당 프로젝트는 간단한 정수형 계산기 앱을 만드는 과제 프로젝트로, 본래는 UIKit 코드베이스로만 개발해서 제출해도 문제 없다.
하지만 그 전에 스토리보드로 먼저 개발해보기로 했다. 스토리보드는 초심자용 UI라고 경시하고 있었는데, 이전에 한 튜터님이 "빠르게 처리해야 하는 외주를 받는다면 스토리보드로 개발할 것이다"라고 말씀하셨던 게 떠올랐기 때문이다.
스토리보드로 기본 UI 구성 |
---|
그런데 진행 도중에 문제가 발생했다.
빌드 오류 Launch screens may not contain user-defined runtime attributes. |
---|
이게 뭔 소리지?
알고보니, Main.storyboard
에 작업해야 하는데 LaunchScreen.storyboard
에 작업해버린 것..
혹시나 하는 마음에 LaunchScreen
에서 작업한 View
들을 Main
에다가 옮겨보려 했지만 불가능했다.
이런 문제는 얼마나 빠른 시점에 발견하느냐가 중요하다. 현재로선 다행히 UI만 구현하고 기능은 구현하지 않았기 때문에, 프로젝트를 엎고 처음부터 새로 작성하는 게 이상적이다. 작업을 온존한 상태로 정상 궤도로 돌리기 위해 억지로 시도해볼 순 있지만, 본래 되지 않는 것을 되게 하는 것은 항상 눈에 보이지 않는 잠재적인 리스크가 따르게 되기 때문이다. 특히나 깐깐해보이는 Xcode에서는 더더욱..
첫 단추를 잘 끼우자: 프로젝트를 시작할 때는 검토, 또 검토.
하지만 한편으로는, 이런 실수를 할 기회가 드물기도 하고, 과제 마감일까지도 여유가 있기 때문에 이 상태로 Main과 Storyboard 내용을 뒤바꿔보기로 했다... 출발!!
가장 먼저 떠오른 방법은 Xcode를 닫은 후 폴더에서 직접 Main
파일과 LaunchScreen
파일의 이름을 서로 바꾸는 것이다.
이렇게 되어있는 파일을 | 이렇게 수정한다 |
---|---|
하지만 예상대로 그렇게 쉽게 굴러가진 않았다. 여전히 빌드가 되지 않는다.
이전에 Storyboard 파일은 XML 코드로 이루어져 있다는 것을 경험을 통해 배웠다. 각 Storyboard 파일에는 고유한 id
를 비롯한 여러 속성값이 XML 형태로 저장되어 있다. 그 내용을 고치지 않는 한 해결은 불가능할 것으로 보았다.
각 storyboard 파일을 소스 코드 (XML) 형식으로 연 모습 ( 파일명은 문제접근1 에서 변경한 그대로 바뀌어 있다: Main ↔ LaunchScreen ) |
---|
Main
과 Storyboard
의 기본 뼈대가 어떻게 다른가 살펴보았다:
<xml>
은 내용이 완전히 같다.<document>
부분과 <dependencies>
부분의 내용이 많이 다르다.<scenes>
내용은 내가 LaunchScreen
에서 작업한 내용이 들어있어서 기본 뼈대를 확실히 비교하기 어렵다.<view>
의 id
값이 다르고, <rect>
의 width
와 height
의 값이 다르다.<viewController>
의 id
값도 다르다.확인한 내용을 토대로 XML 코드를 수정했다.
일단 <document> 와 <dependencies> 를 제외하고 <scenes> 내용을 서로 바꾸었다. |
---|
그 다음으로는 <view> 의 id 값, <rect> 의 width 와 height 의 값을 서로 바꿔주었다. |
---|
혹시 superview에 대한 constraint 설정에도 <view>
의 id
값이 들어가있는지 확인했는데, 검색에 걸리는 것은 없었다.
그리고 서로 바꿨던 Main
과 LaunchScreen
의 파일명도 되돌려주었다.
결과는..
기존 오류 해소 / 새로운 오류 등장: “view controller“ is unreachable because it has no entry points, and no identifier for runtime access via -[uistoryboard instantiateviewcontrollerwithidentifier:]. |
---|
검색해보니 대부분의 결과가 해당되는 View Controller
의 Attributes 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>
부분이다.
새로운 접근 방법이 필요하다.
기존 뼈대를 파악하는 데 돌아가기로 했다. 대신에 이번엔 새로운 프로젝트를 생성해서 그 파일을 참조할 것이다.
새 프로젝트 생성 |
---|
초기 상태의 LaunchScreen 과 Main 의 XML 코드를 살펴보자 |
---|
그랬더니 상당히 신기한 점을 발견했다.
분명히 새 프로젝트를 생성했는데, LaunchScreen
의 initialViewController
id값과 Main
의 initialViewController
id값이 계산기 프로젝트의 것과 동일한 값이 쓰이고 있었다: BYZ-38-t0r
, 01J-lp-oVM
(어쩌면 같은 탬플릿에서 생성했으니 같은 id값이 초기값으로 주어지나보다). 어찌됐든 이제 완전히 초기 상태의 기본뼈대를 파악할 수 있게 되었다.
<xml>
, <document>
, <viewController>
부분이 다르다.아까 비교했을 때와는 완전히 다른 결과다.
<xml>
은 같고, <depenencies>
는 한 줄 차이나고 <rect>
의 크기 설정조차 달랐는데..
LaunchScreen에서 작업하면서 XML 코드가 수정된건가?
초기 상태의 기본 뼈대를 기존 프로젝트에 하나씩 덮어씌웠다. |
---|
결과는?
성공!!! |
---|
LaunchScreen에 Main 내용을 작업해버렸을 때, 해결 방법은 다음과 같다:
성공해서 기쁜 건 맞지만, 아직도 이 방법이 안전한 방법인지 잘 모르겠다. 근본적인 예방 방법은 '실수로 LaunchScreen에 작업하지 않기'이다. 그리고 실수하더라도 빠르게 파악하기 위해 '자주자주 빌드 및 실행해보기'를 실천하는 게 좋겠다. 그래도 XML 코드를 들여다보면서 독특한 트러블슈팅을 해본 건 의의가 있다고 생각한다. 처음부터 새 프로젝트를 생성해서 기본 뼈대를 비교했으면 시간 단축이 되지 않았을까 하는 생각도 든다..!
오늘도 한바탕 삽질했다 xP
아 누가누가 Swift 공부 안하고 xml 전문가 될라고한다🤨!!!! 와 저는 1-3 새로운 오류 등장 쯤에 포기했을 거 같은데 결국 해내신 결말을 보고 존경심이 듭니다. 그래도 xml을 쓸 일이 언젠간 또 있을 거 같은데 그때 분명히 오늘 쌓은 이해도를 발휘하실 수 있을 거예요! 그리고 스토리보드로 작업하고 오토레이아웃 넣어보는 거 꼭 한번 이상 경험해야 한다고 생각합니다. 과제 화이팅!!!!!