태그 보관물: iphone

Objective-C는 Swift의 친구가 될 수 있을까?

이제는 Swift도 꽤나 익숙하게 들리는 언어가 되었습니다. 저에게만 그런가요?
아마도 Swift를 배우고 있거나 실제로 사용하는 분들도 꽤 계실거로 생각됩니다. 저도 아직까지는 Objective-C가 훨씬 편하고 익숙하지만, 그래도 Swift를 아예 무시할 수는 없겠죠. 언제 애플이 Objective-C를 팽할지 모르니까요… 또르르..
Apple_Swift_Logo

Swift 로고
[출처 : Wikipedia – http://en.wikipedia.org/wiki/File:Apple_Swift_Logo.png ]

 

지난번 글에서는 너무 Swift를 부정적으로만 표현한 것 아닌가 싶기도 하고, 지금은 좀 더 Swift의 많은 면을 볼 수 있어서 지난번과는 조금은 다른 관점(?)으로 글을 쓸 것 같아요. 더 좋은 쪽으로!?

요즘에는 왠만하면 프로젝트 내에서 신규 클래스는 Swift로 작성하려고 노력중입니다. 이렇게 Objective-C랑 짬뽕혼합하여 사용하다보니, 그리 나쁘지만은 않더라구요. Objective-C의 장점과 Swift의 장점을 모두 취할 수 있으니까요.유후

Swift와 Objective-C를 한 프로젝트에서 함께 활용할 수 있는 방법은 애플에서 도큐먼트에 친절히 적어두었어요. 참고하세요.

하.지.만. 언제나 그렇듯 위험은 곳곳에 숨어있습니다. 두 언어의 차이점에서 비롯된 이점도 있지만 문제점도 분명히 드러납니다. 좋은점이 있으면 좋지 못한 점도 있기 마련. 좋은 점과 좋지 못한 점, 둘 중 뭐를 먼저 알고 싶으세요? 아마도 좋지 못한 점이 먼저 나오는게 좋을 것 같아요 ㅎㅎ 사실 좋지 않은 점이라기 보다는 그냥 제가 삽질한 것들이라… 후우… 그냥… 뭐랄까.. 넋두리… 네… 그렇습니다. 여러분들은 겪지 않으시길 바라면서! 하핳

제가 겪었던 빅삽질 들을 소개합니다!

b0036170_2231044

오예, 역시 프로그래밍은 삽질이 제맛이지

두 언어에는 서로 가지지 못한 것들이 존재합니다. 같은 듯 다른 듯 비슷한 기능들도 많은데요, 그 중 하나 카테고리(category)익스텐션(extension)이 되겠습니다.
Objective-C에서 저는 카테고리를 굉장히 즐겨쓰는 편입니다. 확장의 용이성과 간편함 때문인데요, 그에 대적할 기능이 스위프트에서는 익스텐션이라 말할 수 있겠습니다. 이에 관련된 에피소드를 소개합니다.
기존 프로젝트에서 저는 NSDictionary의 카테고리로 customMethod라는 메소드를 생성해 줬어요. 그런데 스위프트에서 코딩을 해주다가 저도모르게 NSDictionary의 익스텐션으로 customMethod라는 녀석을 만들어줬지 뭐예요? 서로 다른 이름의 기능이지만, 실제사용은 거의 똑같은 두 녀석. 결과는 어떻게 되었을까요?

13784314429c0c5517edf2134

결과는 카테고리의 승리였어요.

스크린샷 2015-03-11 오후 6.14.52

같은 이름으로 메소드를 호출해 주었을 때, 카테고리의 메소드가 호출이 되더라구요.  왜 그런가 곰곰이 찾아보고 고민해 봤는데, 아무래도 기능의 특성상 그런 것은 아닐까 조심스레 추측해 봅니다. 카테고리는 기존 클래스에 정의되어있는 메소드를 오버라이드 할 수 있습니다. 하지만 스위프트의 익스텐션은 그것이 불가능 하지요. 그렇기 때문에 런타임에서 유연하게 동작하는 특성과 오버라이딩이 가능한 특성 때문에 카테고리 메소드가 우위로 호출되는 것 같습니다. 그것도 모르고 저는 왜 자꾸 다른 결과물이 나오는지 갑갑해서 잠시 이성을 잃었답니다. 여튼, 이런 다르면서도 비슷한 기능들을 사용할 때, 주의해야겠어요.

또 한가지는 튜플(tuple)이었는데요, Objective-C에서는 튜플이라는 자료형이 존재하지 않지요. 다른 언어에도 있지만 Objective-C에서는 사용할 수 없던 녀석인데, Swift에서는 더 쉽게 사용할 수 있어서 몇몇 메소드에 적용을 해 봤어요. 그런데 그 메소드를 Objective-C 코드에서 사용해야 할 일이 생긴거예요. 하.지.만. Objective-C에서는 튜플 자료형을 사용하는 메소드에 접근할 수 없어요. 정확히 말하자면 튜플을 사용할 수 없어요(위의 애플 도큐먼트에서 확인 가능합니다). 그래서 Objective-C 메소드로 전달해줄 추가메소드를 작성해 주어야 했지요.

예를들어 위와같은 Swift 클래스에 두 클래스 함수가 구현되어 있을 때, Objective-C에서 commonMethod는 자유롭게 호출할 수 있지만, tupleMethod는 찾을수 없다며 에러를 뱉어냅니다.

스크린샷 2015-03-11 오후 6.29.58

하지만 주의할 점들만 빼면 좋은점들이 훨씬 많지요! 좀 더 유연하게 자신만의 스타일로 코딩을 할 수 있는 스위프트 덕분에 Objective-C에서 복잡하게 구현해야 했던 것들을 좀 더 쉽게 만들어 낼 수 있습니다. 예를들어 연산자 재정의나 제네릭 기능 같은 경우 Objective-C에서 어렵게 구현해야 했던 것들을 좀 더 간편한 방법으로 구현할 수 있는 길이 열리는데요, 이를 Objective-C에서 직접 접근하지 못하는 경우가 있다 하더라도, Swift에서 먼저 처리를 하고 특정 메소드를 통해 리턴해주는 방식으로 구현한다면 두 언어의 장점을 모두 흡수 할 수 있는 아주 멋진 프로젝트가 될 것입니다.

지난 번과 너무나 대조된 글이라서 좀 이상하지요? 예.. Swift는 계속 발전하고 있고, 우리가 만들어 가는 꼼수도 점점 늘어나고 있기 때문일 거예요 ㅎㅎ

결론
Objective-C는 Swift의 친구이자 멋진 동료가 될 수 있습니다! 100% Objective-C, 100% Swift 코드가 아닌 적절히 융합된, 서로의 장점을 가져다 쓸 수 있는 지금과 같은 체제를 계속 유지해 나갈 수 있으면 좋겠습니다. 애플이 Objective-C를 놓지 않고, Swift는 점점 발전시켜 주었으면 하는 바람입니다 🙂
 

Xcode Bots 적용

테스트는 프로젝트에서 빠질수 없는 부분입니다. 테스트를 위해 변경된 앱을 설치해야 합니다. 설치 방법에는 여러가지가 있습니다. 여러가지 방법 중 Hey 프로젝트에서 적용한 방법을 공유하려고 합니다.

Hey?

Hey는 글로벌 버전 소셜데이팅 서비스입니다. 매일 오전 10시 3명의 이성의 프로필을 확인하고 서로 호감이 있으면 채팅을 할 수 있습니다.

Hey_Timeline Hey_Profile Hey_Chat

테스트 버전 배포

앱스토어에 업로드가 아니라 테스트를 위해 사내에 배포할때 어떤 방법을 사용하시나요?
이음에서는 두가지 방법을 이용했습니다.

  1. 디바이스를 연결하고 Xcode에서 직접 실행해서 앱를 설치해준다.
  2. Adhoc을 이용하여 사내 메일로 공유한다.

1번 방법은 작업중에 설치해줘야 할 경우 방해를 받게 됩니다. 그리고 테스트 디바이스로 등록되지 않은 디바이스때문에 Provisioning을 새로 생성해야 하는 문제가 발생합니다. Debug/Release로 빌드했는지 확인해야 합니다.

adhoc adhoc2 adhoc3

2번 방법은 1번 보다 더 효과적입니다. 한번 메일을 공유하면 앱을 설치해주느라 방해받지 않아도 됩니다. 하지만 불편한 배포과정이 남아 있습니다. Archive -> Distribute -> Adhoc 이런 방법으로 Adhoc버전으로 바이너리를 만듭니다. 그리고 생성된 ipa, plist 파일을 미리 입력한 url에 맞게 서버에 업로드합니다. 여기까지가 끝이지만…. 제대로 올렸는지 확인하기 위해 직접 다운로드해봐야 합니다.

두가지 방법 다 만족스럽지 못합니다.

그래서 새로운 기능인 Bots에 관심이 생겨서 직접 적용해 보았습니다.

Bots ?

Xcode BotsXcode5에 새로 추가된 기능입니다. Bots은 Xcode만을 위한 CI입니다. Bots은 간편하게 설정할 수 있습니다. XCTest를 사용할 경우 실제 등록된 디바이스에서 테스트를 실행하고 결과를 리포트해주는 기능도 있습니다.

bot_viewer-summary_2x 지속적인 통합을 위한 Bot

Bots 설치방법

http://meetkei.com/?p=3196

프로젝트 적용

HeyRelease Bot 생성

createHeyReleaseBot1

Hey Scheme 의 Bot을 생성합니다.

createHeyReleaseBot2

일일 빌드를 위해 매일 오후 5시에 빌드되도록 일정을 설정합니다.

createHeyReleaseBot3

빌드 성공시 프로젝트원 모두 메일을 받을 수 있도록 설정합니다.
실패시 개발자들만 메일을 받도록 설정합니다.
Create Bot 클릭하면 바로 통합이 진행됩니다.

HeyReleaseBuildError HeyReleaseBuildSuccess

통합 결과에 맞게 실패, 성공 메일을 받습니다.
디바이스에서 성공 메일을 확인한 후 제품 다운로드를 클릭하면 설치가 진행됩니다.

이제 통합을 매일 하는 일만 남았습니다!

문제 발생

통합메일에서 다운로드받은 앱을 실행해보니 서비스중인 서버(RealServer)로 접속하고 있었습니다. 테스트를 위해서 RealServer와 테스트 서버(TestServer) 모두 테스트가 가능해야 합니다. 이대로면 TestServer에서 테스트하기 위해서는 기존 방법을 이용해야 합니다.

RealServer로 접속하는 이유

Bot은 통합과정에서 Release build를 하게 됩니다. Build Settings 와 Server Host를 결정하는 Macro때문에 HeyRelease는 RealServer로만 접속됩니다.

HeyRelease_preprocessor

Build Settings > Preprocessor Macros 의 설정을 보면 Debug 에서 DEBUG=1 이 존재합니다. Release 에는 DEBUG가 존재하지 않습니다.

Header 에 적용한 Macro입니다. DEBUG가 존재하면 TestServer로 아니면 RealServer로 API_HOST가 정해집니다. 통합 중에는 Release 로 빌드가 되므로 API_HOST는 TestServer가 됩니다.

그럼 테스트 서버로 연결하려면?
Release에서도 DEBUG를 설정하면 됩니다.

그럼 RealServer, TestServer 를 모두 테스트하고 싶으면?
음…..

Hey에 적용한 방법

여러가지 방법을 생각해본 결과 제가 선택한 방법은 Target을 하나 더 생성하는 것입니다. HeyRelease는 RealServer로 HeyDebug는 TestServer로 접속하도록 하였습니다. Bot을  2개 생성해서 필요할때 둘중 하나를 배포합니다.

  1. 현재 Target을 복사해여 새로운 Target을 만듭니다.
  2. Preprocessor Macros 를 설정합니다.
  3. HeyDebug 이름으로 Bot을 생성합니다.

HeyDebug_preprocessor

createHeyDebugBot1 createHeyDebugBot2 createHeyDebugBot3

단점

  • build settings이 변경되면 두개의 Target 에 적용해야 함
  • 파일 생성 및 추가시 두개의 Target 을 지정해야 함

targets

언급한 단점이 있지만 Bots을 빠르게 적용할 수 있는 방법입니다. 개선된 방법은 조금 더 고려해 볼 예정입니다.

Bots Error

처음 Bots을 사용하면 많은 오류들과 만나게 됩니다. 몇가지 오류 해결 방법을 정리하였습니다.

Provisioning Profile 관련 오류

ProvisioningProfileError

iOS Team Provisioning Profile 을 사용하면 문제가 해결됩니다.

GeneralIdentity

그래도 해결되지 않는 경우 Target > General > Identity 에 위와 같이 Provisioning Profile 오류로 인한  Fix Issue버튼이 표시되는 경우가 있습니다. 이 버튼을 클릭하고 수정된 상태에서 통합을 진행해 보세요.

Reason: XCSCredentialSSHKey: private key is missing from the credential

http://stackoverflow.com/questions/5525436/xcode-could-not-find-a-valid-private-certificate-valid-key-pair-for-this-profile

xcode bots User interaction is not allowed.

  • Open the Keychain Access
  • Right click on the private key
  • Select “Get Info”
  • Select “Access Control” tab
  • Click “Allow all applications to access this item”
  • Click “Save Changes”
  • Enter your password

http://stackoverflow.com/questions/577750/running-xcodebuild-from-a-forked-terminal

Bots 오류 모음

  • Repositories that require an SSH key to access
  • Code Signing and Provisioning Profiles
  • Submodules
  • I made a mistake and now I can’t fix the repository from Xcode!

http://ikennd.ac/blog/2013/10/xcode-bots-common-problems-and-workarounds/

Profile