iOS 삽질 : 릴리즈 빌드에서만 런타임에 에러 발생

앱을 만들다가 Debug 에서 잘 실행되는것을 확인하고 TestFlight 에 올려서 테스트 하는데 앱을 시작하자 마자 크래시가 발생하는 문제가 발생했습니다.

발생한 에러는 다음과 같았습니다

2017-04-03 15:12:19.049 daangn[48068:1047076] Unknown class _TtC6daangn17NotificationTabVC in Interface Builder file.
Could not cast value of type 'UIViewController' (0x112194288) to 'daangn.NotificationTabVC' (0x10bdc09c8).

이렇게 저렇게 해결 방법을 찾다보니 Swift 의 Release Scheme의 Optimization Level 을 ‘Fast, Whole Module Optimization’ 에서 None 으로 변경하면 잘된다는 글을 발견하고 그대로 해봤더니 정말이지 Release scheme 에서도 에러가 발생하지 않았습니다.

좀더 정확히는 ‘Fast, Whole Module Optimization’ 이 아닌 ‘None’, ‘Fast, Single-File Optimization’ 로 변경하면 앱이 종료되지 않았습니다.

Optimization 의 버그 인가 싶어서 에러 메시지에서 못찾는다고 나온 클래스만 별도의 IB 로 분리하거나 스토리보드로 분리해보고 Derived Data 도 지우고 Clean Build 도 해봤지만 문제는 해결되지 않았습니다.

이렇게 하루내내 삽질을 하다가 원인을 찾았는데 그건 제가 사용하는 라이브러리의 문제 였습니다. 저는 좌우로 스크롤되는 VC를 구현하기위해 XLPagerTabStrip 이라는 라이브러리를 사용하는데 이 라이브러리에서 사용하는 코드 구현 방식에서 어쩔수 없이 오류가 발생하는 부분이 있었습니다.

해결 방법은 생각보다 간단한데요. AppDelegate 에서 앱이 시작되고 XLPagerTabStrip 을 사용하는 코드가 호출되기 전에 XLPagerTabStrip 을 사용하는 VC를 한번 호출해주면됩니다.

let _ = NotificationTabVC(nibName: nil, bundle: nil)

위와 같이 한번 호출해주면 실제 사용할때 에러가 발생하지 않습니다. 이 에러는 이슈에도 올라와 있는데 Swift 의 Interface Builder 의 Generic 지원 문제로 인해 발생하는 문제 였습니다.

이런 삽질은 할때 마다 너무 힘드네요. 안그래도 Swift 빌드 느린데 빌드를 몇십번씩 하면서 테스트 하려니 중간에 다른것도 못하고 멍하니 화면만 바라보면서 이번엔 잘되라 하면서 기도하고 있으니 시간도 아깝구요.


진정한 삽질이란 이런걸까요? 작년 11월의 제가 이와 동일한 문제를 이 블로그에 iOS 삽질로 적었었네요… 글 다 작성하고 나서 아래 관련게시글로 나와서 알게됬습니다. ㅜㅜ https://code.iamseapy.com/archives/36

게시글의 아마존, iTunes 링크들을 통해 구매를 하시면 제휴(Affiliate) 프로그램에 의해 저에게 일정 금액이 적립될 수 있습니다. ^_____^

iOS 삽질 : Unknown class xxx in Interface Builder file

아이폰 개발은 하루하루가 삽질의 연속이네요… 오늘의 삽질은 클래스 파일을 찾을수 없다고 하면서 앱이 종료(크래시)되는 현상을 고치면서 발생했습니다.

인터페이스 빌더의 ViewController에 새로 만든 VC를 지정 했고 개발 빌드까지 아무 이상이 없었습니다. 그런데 테스트 플라이트를 통해 받은 Production 빌드에서만 앱이 크래시 나길래 Xcode에 아이폰을 연결해 실행하니 앱이 종료될때 다음과 같은 메시지가 있었습니다.

daangn[19282:4846848] Unknown class _TtC6daangn15MyArticlesTabVC in Interface Builder file.
Could not cast value of type 'UIViewController' (0x1b453af60) to 'daangn.MyArticlesTabVC' (0x1072c0028).
daangn[19282:4846848] Could not cast value of type 'UIViewController' (0x1b453af60) to 'daangn.MyArticlesTabVC' (0x1072c0028).

MyArticlesTabVC는 분명히 존재하는 파일이고 UIViewController 하위 클래스가 맞습니다. 그리고 개발 빌드에서는 아무 문제가 없었죠 ~

제가 문제를 겪은 VC는 XLPagerTabStrip 라이브러리의 특정 VC를 상속받은 거였고 이와 비슷한 문제가 이슈에 등록되어 있었습니다.

Can’t connect ‘containerView’ and ‘buttonBarView’ outlets #141

상속받는 클래스가 Generic 클래스 인데 Xcode 문제로 인터페이스 빌더의 커스텀 클래스에는 Generic 클래스를 지정 할 경우 이와 같은 오류가 발생한다고 하네요. 해결은 간단하게도 AppDelegae의 didFinishLaunch 함수 제일 위쪽에 다음과 같은 코드를 추가해서 했습니다.

let _ = MyArticlesTabVC(nibName: nil, bundle: nil)

이문제는 이전에도 한번 경험해봐서 알고는 있었는데 그때는 개발 빌드에서도 앱이 종료 되었었는데 이번에는 개발빌드는 정상동작하고 Production 빌드에서만 문제가 발생해서 찾기 어려웠습니다.

참고문서

게시글의 아마존, iTunes 링크들을 통해 구매를 하시면 제휴(Affiliate) 프로그램에 의해 저에게 일정 금액이 적립될 수 있습니다. ^_____^

컴파일러 친화적으로 Swift 코딩 하기 싫다

swift
swift

swift는 생긴지 얼마 안된 언어지만 iOS, macOS 개발을 위해서는 어쩔수 없이 사용하게 되는데요. 개발을 하다보면 제일 문제되는건 swift 언어 컴파일 시간 문제입니다.

Xcode 에서 아이폰 개발을 하다보면 이전에 Obj-C 사용하던것 보다 컴파일이 느려서 시뮬레이터로 실행하면서 코드 수정하는 전체 프로세스를 느리게 만들정도죠.

그래서 swift로 개발할때는 고려해야 될게 생겼습니다. 컴파일러 친화적으로 코딩하기! ㅜㅜ 컴파일러의 컴파일 속도를 올려주는 팁들이 몇개 있는데 이걸 잘지키면 컴파일 속도가 빨라집니다.

제가 참고로한 2개의 글에 자세히 설명되어 있으니 읽어보시기를 추천드립니다.

대표적인거 몇개 소개해드리겠습니다.

rightView?.bounds.width ?? 0

위와 같이 값이 nil 이면 기본값을 제공하는 연산자는 코드 가독성도 좋아서 많이 사용하죠 ~ 그런데 이걸 아래와 같이 풀어 쓴다면 컴파일 속도가 얼마나 빨라질까요?

var width: CGFloat = 0
if let rightView = rightView {
 width = rightView.bounds.width
}

빌드 타임이 99.4% 빨라졌다네요… 5238ms 에서 32.4ms 로 빨라져요. (위의 예제는 벤치마크 코드의 일부라서 실제로 위의 코드로 하면 격차가 줄어들수도 있어요. 전체 코드는 링크 참고)

이런코드 100번 쓰면 5초 * 100 = 500초… 8분정도 느려지는거네요. 8분을 아끼기 위해서 1줄 코드를 4줄짜리로 바꾸면 100줄 짜리 코드가 400줄 될거구요.

이외에도 아래와 같은 것들이 있어요

  • 배열에 값을 추가할때 + 연산자 대신 append를 사용하면 97.9% 속도 향상!(1250.3ms -> 25.5ms)
  • 삼항 연산자를 사용하지 않으면 빌드타임 92.9% 향상!(239ms -> 16.9ms)

이런…. 다들 코드 가독성 향상이나 편리함을 이유로 코드에서 자주 사용하는것들이네요…

Swift 3에서는 그래도 이런것들이 조금 개선되었다고 합니다.

자 여러분의 선택은? 가독성을 포기하고 1줄코드를  3줄씩 늘려서 쓰고 컴파일 속도를 얻을것인가? 컴파일 속도를 포기하고 가독성이나 편리함을 추구할것인가요? 다른 옵션으로 iOS 8 지원을 포기하고 swift 3으로 넘어가는 선택도 있겠네요. 아니면 컴퓨터를 맥프로(맥북프로 아닙니다… 쓰레기통 맥 말하는거에요) 최고급 사양으로 바꾸는 선택지도 있겠네요 ㅎㅎ

저는 컴파일 속도를 포기했습니다… swift 3에 컴퓨터 사양 높이는걸 고려하겠어요

옛날 옛적에 ~ C로 코딩할때는 컴파일러 속도를 빠르게 하기위해 코딩 습관도 컴파일러 친화적으로 하고 컴파일러가 새로 나올때마다 공짜점심을 먹었다는 이야기를 들었는데… 요즘 세상에 이런 이야기를 할줄은 몰랐네요 ㅜㅜ 개발자들을 위해 Swift 컴파일러가 좀더 빠른 속도로 개선되었으면 좋겠습니다.

참고 자료

게시글의 아마존, iTunes 링크들을 통해 구매를 하시면 제휴(Affiliate) 프로그램에 의해 저에게 일정 금액이 적립될 수 있습니다. ^_____^