IBDesignable은 xib파일에서 작업한 결과물을 다른 xib나 스토리보드에서 바로바로 확인 할 수 있게 해주는 편리한 툴입니다. 기본적인 사용법은 이 포스트를 참조해주세요.
하지만 안타깝게도, IBDesignable을 사용했을 때 주의하지 않으면 다음과 같은 에러들을 만나게 되기도 합니다.

이런 에러를 만났을 때 제대로 대처하지 못한다면, IBDesignable은 그저 생산성을 저하시키는 툴밖에 되지 않겠죠. 이 글에서는 IBDesignable을 사용하면서 만날 수 있는 에러 메시지들과, 그에 대한 대처법, 주의할 사항을 알아보도록 하겠습니다.
들어가기 전에, 간단한 배경지식
InterfaceBuilder는 iOS Simulator위에서 돌아간다.
IB는 결코 정적인 그림판이 아닙니다. 그것은 실시간으로 돌아가고 있는 Simulator의 화면입니다. 우리가 직접 Command+B를 눌러서 빌드를 하지 않아도, Xcode를 키거나 IB 파일을 열었을 때 Xcode에서 빌드가 돌아가는 이유가 바로 그 때문이죠.
그리고 Simulator는 우리가 Command+R을 눌렀을 때 앱이 올라가는 시뮬레이터와는 별도의 시뮬레이터일 수 있고, 만들어지는 Bundle도 다른 Bundle일 수 있습니다. 이 점만 기억하면 아래의 여러 에러들을 훨씬 쉽게 이해하고 다룰 수 있습니다.
ErrorMessage 1 : Agent Crash
IBDesignables: Failed to update auto layout status: The agent crashed
이런 종류의 메시지가 떴다면, 이는 운이 좋은 경우입니다. IBDeignable을 렌더링하던 시뮬레이터에서 크래시가 발생했기 때문에, 그 크래시 로그가 남게 되고, 그 로그를 분석하면 어디서 문제가 발생했는지 알 수 있기 때문입니다.
cd ~/Library/Logs/DiagnosticReports ls | grep ‘IBDesignablesAgent-iOS*’ // 이 결과 물 중 가장 최근 파일을 연다. // 혹은 아예 이 명령을 shellScript로 만들 수도 있습니다. ls ~/Library/Logs/DiagnosticReports | grep ‘IBDesignablesAgent-iOS*’| tail -1 | xargs open
위 명령을 치면 다음과 같은 크래시 로그를 볼 수 있다.

기본적으로 IB는 파일의 `awakeFromNib`과 `prepareForInterfaceBuilder` 를 실행합니다. 따라서 사실 굳이 크래시 로그를 보지 않더라도, 대부분의 오류는 그 두 군데를 잘 살펴보면 알아낼 수 있습니다. 그리고 사실 그 두 군데에서 크래시를 유발 할 수 있는 실수들도 어느 정도 정해져 있습니다.
- Bundle.main에서 Asset을 불러오거나 그것을 참조한다.
우리에게 main인 번들이 IB simulator에게는 main이 아닐 수도 있습니다. 따라서 우리가 AssetCatalogue에 넣어둔 Asset들이 IB simulator에서는 nil이 될 수도 있지요. 언제나 Bundle.main을 직접 부르지 말고 `Bundle(for: MyViewClass.self)`를 통해 Bundler을 참조해야 합니다. 무엇보다도 force-unwrapping은 그냥 전체적으로 하지 않는 것이 좋습니다.
2. 작업중에 nil을 참조하는 코드를 `awakeFromNib` 등에 두고 빌드한다.
개발을 하는 도중에는 말도 안 되는 코드들을 쓰게 될 때가 있다. 예를 들어
let a:String? = nil
let b = a!.count
print(b)
이런 코드가 `awkeFromNib`이나 `prepareForInterfaceBuilder` 안에 들어있다면, 우리의 앱이 Crash 나듯, IBAgent도 Crash 납니다.
따라서 `AgetnCrash` 관련 오류가 났다면
1. 실제로 빌드를 해서 실행시켜 본다. 그랬는데 크래시가 나면 당연히 IB에서도 크래시가 난다.
2. 실행시켰는데 크래시가 나지 않는다면, awakeFromNib이나 prepareForInterfaceBuilder에서 Bundle.main을 참조하는 코드가 있지 않은지 확인한다.
주의 사항
- CrashLog는 바로바로 만들어지지 않을 수도 있다. 크래시로그는 그 이름에 만들어진 날짜/시간이 표시되므로, 언제나 그 생성시점을 확인하고 읽어야 한다.
- 때로 CrashLog는 Xcode를 껐다가 켜야 만들어 질 수도 있습니다.
ErrorMessage 2: Library not loaded
이 에러는 좀 더 다루기 까다롭습니다. 디버깅 할 수 있는 방법이 많지 않고, 또 실제로 어떤 문제가 있어서 라이브러리를 로드하는데 실패한건지, 혹은 “아직” 라이브러리를 다 로드하지 못한 것인지 확인하기 어렵기 때문입니다.
본질적으로 이 에러는 다음 사진이랑 비슷한 상황입니다.

Cocoapod을 install하고 빌드를 하지 않으면 당연히 모듈을 불러올 수 없습니다. 이 때는 당연히 pod install → Build하면 문제가 해결됩니다.
문제는 그렇게 했는데도 다음과 같은 에러메시지가 보일 때다.
Library not loaded: @rpath/Alamofire.framework/Alamofire ….
결론적으로 저 `@rpath` 가 IBAgent 시뮬레이터와 다른 여타 시뮬레이터가 다르기 때문에 생기는 문제입니다. `@rpath` 는 Xcode→ProjectSetting→BuildSetting→Runpath Search Paths 에서 확인 할 수 있습니다.
기본적으로 `@executable_path/Frameworks`와 `@loader_path/Frameworks`가 설정되어 있습니다. 그런데 안타깝게도 IBAgent와 일반 Simulator 들의 @executable_path/@loader_path 가 다르기 때문에
– `@executable_path/../Frameworks`
– `@loader_path/../Frameworks`
를 다음과 같이 추가해 줘야 합니다.

ErrorMessage 3 : CodeSign
SomeFramework.framework: required code signature missing for ‘SomeFramework.framework’
이는 IBDesignable을 구현한 Pod을 Cocoapod을 통해 설치했을 때 일어날 수 있는 문제입니다.
기본적으로 IBDesignableAgent는 CodeSign을 요구합니다. 그런데 Cocoapod은 pod install을 할 때 모든 CodeSign을 Disable시킨다. 대부분의 경우, 어차피 최종 만들어지는 App에만 CodeSign이 되면 전혀 문제가 없지만, IBDesignable의 경우에는 그 자체가 최종 만들어지는 App이기 때문에 문제가 됩니다.
최근의 Cocoapod에서는 문제를 해결한 듯 보이므로, 최신 버전으로 업데이트를 해결 됩니다. 하지만 모종의 이유로 (팀원들과 같은 Cocoapod버전을 써야 한다든지) 업데이트를 할 수 없다면 Podfile에 아래 코드를 추가하면 됩니다.
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings.delete(‘CODE_SIGNING_ALLOWED’)
config.build_settings.delete(‘CODE_SIGNING_REQUIRED’)
end
end
마치며
IBDesigable은 그 자체로 하나의 UITest가 될 수 있습니다. 위와 같은 여러 에러에 대응하기 어려워서 IBDesignable을 쓰지 않고 있었다면, 지금이라도 용기를 내어 다시 시도해 보기를 권합니다.
Comments