태그 보관물: 삽질

iOS 삽질 할뻔 : Xcode 9.2로 업그레이드하면 앱스토어 업로드 불가

최근 들어 애플의 소프트웨어 버그가 자주 발생해서 말이 많은데 오늘은 개발자들이 macOS, iOS 개발할때 꼭 사용해야하는 Xcode에 심각한 버그가 발생했습니다.

12월 5일(화)에 iOS 11.2 SDK를 포함한 Xcode 9.2 버전이 새로나왔는데요. 이 버전으로 업그레이드후 열심히 개발하는데까지는 좋은데 앱스토어에 앱을 업로드 하려고 하면 오류와 함께 실패한다고 합니다.

2017년 12월 6일(수) 기준으로는 이 문제가 발생하지 않습니다.

아래와 같은 오류가 발생한다고 하는데요. 정식출시된 Xcode 인데 잘못된 버전으로 인식해서 앱스토어에 업로드 할 수 없는 버그가 발생한거죠 ㅜㅜ

ERROR ITMS-90534: "Invalid Toolchain. New apps and app updates must be built with the public (GM) versions of Xcode 6 or later, macOS, and iOS SDK or later. Don't submit apps built with beta software including beta macOS builds."  

해결 방법은 Xcode 9.2를 완전히 지우고 앱스토어가 아닌 애플 개발자 센터 홈페이지에가서 Xcode 9.1 버전을 직접 다운로드 받아서 설치해야 합니다. Xcode 용량이 10기가 정도 했던거 같은데… 인터넷이 느린 저희 집이라면 근처 스타벅스 가서 받아야겠네요.

이 게시글의 제목이 삽질이 아니라 삽질할뻔인 이유는 저는 영향을 받지 않았기 때문입니다!!! 오늘 오전에 Xcode 9.2 업데이트도 했고 앱스토어에 업로드도 했지만 저는 빌드는 bitrise.io 라는 서비스를 사용하고 있기 때문에 영향이 없었습니다. bitrise.io 에서는 여러가지 버전의 Xcode를 가지고 있고 원하는 Xcode 버전만 변경하면 되서 이번 영향에서 벗어날수 있었습니다! bitrise.io 적용한지 몇주 안됬는데 ㅎㅎ 운이 좋았네요.

이 포스트의 bitrise.io 링크를 눌러서 가입하시면 제 무료범위의 빌드 시간이 늘어나는 혜택이 주어집니다! 기본은 10분인데 조금씩 늘어나고 5명이 되면 티셔츠 받을수 있어요!

조만간 시간이 되면 bitrise.io 서비스에 대해서도 글을 적을게요. 개인적으로는 bitrise.io를 빌드 하는데 사용하고 있는데 여러가지 서비스중에 제일 마음에 들었어요. Xcode 베타 버전도 빠르게 지원합니다. 회사에서는 유료 계정으로 사용중입니다.

참고정보

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

iOS 삽질 : iOS 11에서 SearchBar 높이 변경 이슈

iOS 11에서 UISearchBar의 높이가 기존 44에서 56으로 변경되었습니다. 대부분의 경우 큰 문제는 없지만 네비게이션바와 함께 사용하는 경우 높이 변경으로 인해 문제가 발생했습니다.

네비게이션바의 titleView에 UISearchBar를 사용하는 경우 네비게이션바의 높이인 44를 넘어가게 되어 검색이후의 화면에서 네비게이션바 하단에 검정색 공백이 생기는 문제가 있었는데요.

현상

아래 개발화면의 스샷은 왼쪽의 첫번째 화면의 네비게이션바에 UISearchBar가 있고 두번째 화면이 검색결과를 눌렀을때 이동하는 화면입니다.

첫번째 화면과 두번째 화면의 네비게이션 바의 높이가 달라진것을 볼 수 있고 이로 인해 두번째 화면의 네비게이션바 하단에 검정색 공백이 추가됩니다.

이는 앞서 이야기 했던 UISearchBar의 높이가 44에서 56으로 변경된것에 따른 영향으로 첫번째 화면에서는 네비게이션바의 높이가 UISearchBar의 높이에 맞게 56으로 늘어났고 두번째 화면에서는 이전화면의 높이인 56픽셀보다 적은 44픽셀의 네비게이션바를 보여주면서 12픽셀 만큼의 검정색 공백이 생기는 문제입니다. iOS에서 똑똑하게 변경해주면 되는데 이게 처리가 안되더라구요.

해결

우선 첫번째 실패한 해결방법은 SearchBar의 높이를 44로 강제 설정하는것입니다. frame 정보를 변경하는것으로는 안되고 heightAnchor 값을 설정해줘야합니다. 아래 코드를 적용합니다.

if #available(iOS 11.0, *) {
    searchBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
}

이렇게 하면 높이가 44로 잘 변경되지만 UISearchBar에 글자를 입력하기위해 포커스를 가져가면 UISearchBar가 살짝 내려오는 문제가 생깁니다. 이 문제는 어떻게 해결할 방법이 없더라구요 ㅜㅜ

살짝 내려오니까 내가 뭔가를 수정하면 되겠구나 싶어서 삽질을 계속해서 해봤지만 무슨수를 써도 안되더라구요 ㅜㅜ

최종적으로 해결한 방법은 UISearchBar를 감싸는 UIView를 하나 만들고 이 뷰의 frame 값을 강제로 지정하는 것입니다.

class SearchBarContainerView: UIView {
    let searchBar: UISearchBar
    init(customSearchBar: UISearchBar) {
        searchBar = customSearchBar
        super.init(frame: CGRect.zero)
        addSubview(searchBar)
    }

    override convenience init(frame: CGRect) {
        self.init(customSearchBar: UISearchBar())
        self.frame = frame
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        searchBar.frame = bounds
    }
}

let searchBarWrapper = SearchBarContainerView(customSearchBar: searchBar)
searchBarWrapper.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 44)
navigationItem.titleView = searchBarWrapper

이렇게 하면 해결! 첫번째 방법이 깔끔하고 정석대로 해결하는것 같은데 제대로 동작하지 않으니 두번째 방법을 사용할 수 밖에 없었습니다. iOS 개발하다 보면 이런식으로 해결해야 하는 경우가 있더라구요.

삽질지수

이번 삽질의 삽질 지수는 1입니다. (삽질지수 범위 1 5 단계) 처음부터 원인을 알고 있었고 해결방법만 찾으면 되는데 인터넷에 있는 방법중에 되는게 있어서 다행이었죠.

이거 때문에 하루가 그냥 사라졌네요 ㅜㅜ 첫번째 방법으로 깔끔하게 해결하려고 계속 삽질 했던게 원인이었어요. 그래도 해결할 수 있어서 다행이었어요. 해결하지 못하면 네비바 아래에 검색바를 위치시켜야되서 내키지 않았거든요.

참고자료

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

iOS 삽질 : 인터페이스 빌더에서 설정한 색상이 제대로 표시 안됨

인터페이스빌더(interface builder) 혹은 스토리보드(storyboard)에서 디자이너간 준 색상 코드를 입력했는데 이상하게 코드로 입력한 색상과 다르게 보이는 현상이 있었습니다.

코드로 입력한건 잘되는데 인터페이스 빌더에서 직접 지정한 색상의 경우에만 원하는 색상이 표시되지 않았죠. 그래서 찾다 보니 Color Space 의 문제임을 알게 되었습니다.

이거는 맥에서 애플이 제공하지 않는 모니터를 사용할때 Picker 를 이용해서 색상을 선택하면 나오는 문제랑 비슷한데요. 같은 색상 코드라고 해도 Color Space 에 따라서 다르게 표현되는거죠.

하지만 저는 Xcode 에서 Generic RGB를 맞게 설정하고 hex 코드를 입력했음에도 원하는 색상이 표시되지 않았습니다.

xcode 색상 선택기

xcode 색상 선택기

그래서 혹시나 Xcode 가 저기에 지정한 Color Space 를 무시하고 자기 맘대로 하는건 아닐까 싶어서 인터페이스 빌더 파일을 소스보기로 봤더니 역시나 Color Space 를 자기 마음대로 지정하고 있었습니다. Generic RGB 가 당연히 일반 RGB 스페이스라고 생각했는데 이건 애플의 버그 아닌가 싶어요…

- <color key="textColor" red="0.45098039215686275" green="0.4823529411764706" blue="0.51764705882352935" alpha="1" colorSpace="calibratedRGB"/>
+ <color key="textColor" red="0.45098039215686275" green="0.4823529411764706" blue="0.51764705882352935" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>

위 코드의 윗부분은 색상이 잘못 나올때 이고 아랫 부분은 색상이 제대로 나올때 입니다. 보면 colorSpace 값이 calibratedRGB으로 지정 되었을때 색상이 잘못나오는것을 볼 수 있습니다.

그래서 colorSpace 는 custom 으로 변경하고 customColorSpace 를 sRGB로 변경해서 원하는 색상을 표현 할 수 있게 되었습니다.

검색하다보니 Xcode 8에서는 제가 변경한걸로 기본 스페이스가 바뀌었다는데 이상하게 새로 만든 파일에서 계속 이런식으로 적용되더라구요. 이거 때문에 디버깅 뷰 까지 열어가면서 색상 코드 디버깅 하기는 처음이었습니다.

전체 프로젝트에서 저런식으로 잘못 표시된 색상이 있을까 싶어 검색해봤더니 어마어마하게 많더군요… 그래서 아래 명령어로 한번에 변경했습니다.

$ grep -rl 'colorSpace="calibratedRGB"' 폴더/* | xargs sed -i '' 's/colorSpace="calibratedRGB"/colorSpace="custom" customColorSpace="sRGB"/g'

이렇게 해도 나중에 또 색상 지정할때 이런 문제가 발생할 수 있는 여지는 있습니다. 그건 바로 Color Picker 에서 색상을 지정해두고 사용했을때 그 색상을 사용하면 색상을 추가할때의 colorSpace 로 다시 변경됩니다. 그래서 저는 이런식으로 기존에 저장해두고 사용하던 색상을 다 덮어 버렸습니다.

색상 피커 저장된 색상 지움 ㅋ

색상 피커 저장된 색상 지움 ㅋ

지우는 방법을 몰라서 그냥 안쓸거 같은 색상으로 덮어 버렸어요.

http://stackoverflow.com/a/27283783 글을 보면 칼라 피커에서 hex 코드를 입력하면 Color Space가 원복된다는 이야기도 있네요… 제 문제도 이 경우에 해당하는것 같아요. 이런식이면 인터페이스 빌더에서 색상입력하지 말라는거나 다름없지 않나요…. RGB 코드 따로 입력하는게 얼마나 귀찮은데

애플의 이 정책은 나름 모니터마다 같은 색상을 보게하려는 의도라고는 하던데 이것 때문에 오히려 원하는 색상을 표시 못하는 경우가 더 많은거 아닌가 하는 생각이 들었습니다.

제가 제대로 이해하지 못하고 삽질을 해결한것 같아서 여전히 찝찝합니다. 더 좋은 방법을 알고 계신분은 댓글로 알려주세요 ~

덧. 아마도 이 문제는 아이맥이나 애플이 만든 모니터를 사용한다면 발생하지 않을것도 같아요. 색상 피킹하는 툴은 아이맥이나 애플이 만든 모니터에서는 괜찮았거든요…

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

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) 프로그램에 의해 저에게 일정 금액이 적립될 수 있습니다. ^_____^