아이폰 개발 – NSURLConnection , NSRunLoop, NSOperation

기본적으로 NSURLConnection 은 Async 모드를 제공해 준다. 그런데 이걸 Thread 에서 동작하도록 수정을 해볼려고 하니, 삽질의 연속이다.

결국 쉽게 가기 위해서 선택한 것이(사실 NSThread 는 사용하지도 않았다는) NSOperation 이다.

그런데 이상한 현상은 NSOperation 안에서 NSURLConnection 을 사용하게 되면 NSRunLoop 를 이용해서 Message Pumping을 하게 되는데, 아직 이 부분을 완벽하게 이해하지 못한 죄로!!!

GET은 잘 되는데 POST는 이상하게 동작한다.( 이유는 아직 잘 모르겠다 –_- )

처음에는 아예 NSURLConnection 이 동작하지 않는다고 생각했는데, async의 경우에 해당 Runloop로 메시지를 보내는 것이라, 타 스레드에서 제대로 받지 못해서 발생하는 문제인듯 하다. –_- 그런데 이게 해결책으로 제시된 걸 써봐도 제대로 동작하지가 않아서 좀 더 고민을 해야 할 듯 하다.

iPhone library, framework 위치

  음… 중간에 삽질했던 것 중에 하나가, iPhone 개발시 추가하는 Library, framework의 위치를 잘

몰랐다는 것이다.

 

 잊지말자.

 

Developer/Platforms/iPhoneOS.platform/Developer/usr/lib

Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks

 

아이폰 개발자 인증 과정에서 주의할 점!!!

오래간만에 다시 아이폰에 프로그램을 올리기 위해서, 인증서를 등록하는데, 맥장비를 엎는 바람에 새로 인증서를 발급해야 했는데, 자꾸 인증서가 등록이 되지 않는 것이다. 이유를 오늘 드디어 찾았는데!!!

원인 1 : 키체인 접근 –> 인증 지원 –> 인증 기관에서 인증서 요청 시에 여기서 생성하는 키 정보가 “로그인” 으로 들어가야 한다. 이것은 로그인 키체인 위에서 “로그인”을 기본 키체인으로 만들기를 선택해야 한다. 기본적으로는 로그인이 기본 키체인 이므로 걱정하지 않아도 되지만, 이 점이 매우 중요하다.

원인 2 : 인증서 관련 정보가 바뀌면 반드시 XCode 에서 Clean All Targets 를 선택해서 관련 정보를 삭제해 줘야 한다. 단순히 XCode 를 종료하고 다시 시작하는 것만으로는 해당 정보가 남아있어서 반영되지 않는다.

원인 3 : Provisioning 관련 파일을 아이폰과 XCode 두 군데에 등록해야 한다. 등록 방법은 XCode의 Windows->Organizer 를 선택해서 등록할 수 있다.

보통 인터넷으로 기본적으로 인증서를 등록하는 방법을 따르면 잘 되지만, 혹시나, 이런 문제가 발생할 수 있기 때문에, 이에 대해서 잘 숙지하고 있는것이 꼭 필요하다.

아이폰 프로그래밍 시작하기-2 Nib 와 loadView의 관계

필자, 역시, 아이폰 프로그래밍은 이제 막 시작하는 거라, 완전 밑바닥 부터 공부를 하는 중이다.

(과연 공부를 하고 있냐고 물으신다면, 아니라고 쿨럭…)

사실, 몇달전에 간단한 아이폰 어플을 만든 적은 있지만, 그 때는, 내부 구조를 전부 C++로 만들고, UI만 아이폰 컨트롤을 조금 써서 만들었었다. 그 때의 목표는 Windows Mobile 어플과 아이폰 어플의 로직을 같은 코드로 공유하는 것이었다.

그런데, 그 때도 잘 이해하지 못하고 넘어갔던 것들이 nib 와 각 컨트롤러의 동작들이었는데, 이번에 그 부분을 공부할려고 하니 완전히, 삽질의 바다에서 헤메이는 것이었다. 이래서 물어봐야 하는데, 안 물어본 쿨럭…(혼자서 할 수 있을꺼라고 생각하다니 T.T 주변에 아이폰 프로그래밍 잘하는 사람들이 수두룩 한데 쿨럭…)

그러나, 책을 보고, 예제를 고쳐보고 곰곰히 생각해보니 다음과 같은 관계가 간단하게 성립한다.

image

이 부분을 잘 몰라서, NIB를 안 쓸려고 하니, 화면이 나오지 않는다든지, 또는 원하는 동작이 일어나지 않는다든지 한 것이다. 그렇다면 NIB를 안쓰고 할려면 위의 Nib 가 해주는 역할을 개발자가 대신 해줘야 하는 것이다.

1) NIB를 사용할 경우

– (void)applicationDidFinishLaunching:(UIApplication *)application {   
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

2) NIB를 사용하지 않을 경우 – MainWindow.xib 는 쓸 경우

– (void)applicationDidFinishLaunching:(UIApplication *)application {  
    HelloController *viewController= [[HelloController alloc] init];
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

2) NIB를 사용하지 않을 경우 – 전체 사용 안함

– (void)applicationDidFinishLaunching:(UIApplication *)application {  
    UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    HelloController *viewController= [[HelloController alloc] init];
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

다른 부분들도 바뀌어야 하는 부분들이 있지만, nib를 안쓰면 다음과 같이 코드 부분들이 늘어나는 것을 알수 있다.

아이폰 프로그래밍 시작하기-1 프로그램 실행 아이콘과 로고화면

아이폰 프로그래밍을 하면서 보통 Objective-C 나 ViewController, NavigationController 를 사용하는 방법에 대해서 알려주시만…

그것보다 더더욱 중요한(?) 프로그램 실행 아이콘과 로고화면을 바꾸는 방법에 대해서는 내용이 별로 없다 –_-

그러나 엄청 쉬운 방법 –_-;

그럼 어떻게 하느냐?

  파일명 사이즈
프로그램 실행 아이콘 icon.png 60×60
프로그램 로고 화면 Default.png 320×480

여기서 중요한 것은 프로그램 로고 화면의 이름이 첫글자가 대문자 D라는 것이다.

(사실, 이건 대소문자 구별할 경우에 문자가 되는 부분이다.)

그리고 Project 에 추가하면, 바로바로 코드를 지정하지 않아도 지정되는 모습을 볼 수 있다.

아이폰 Device 빌드 시 주의사항

  나를 한참을 괴롭히던 문제,

 

 개발자 등록을 하고, 이를 통해서 빌드를 할려고 하는데, 자꾸 Provisioning 이름이 기본 설정과 매치 되지 않는다고 빌드가 되지 않았다.

 

 알고보니, 인증서의 이름과, Info.plist 의 Bundle Identifier 가 동일해야만 패스된다. T.T

 

 

NSUnknownKeyException

IPhone 책의 예제를 따라하다가, 위의 에러가 나면서 자꾸 프로그램이 죽는 현상이 발생했다. 해당 에러가 먼지도 모르고 계속 보고 있다가(사실 처음에는 위의 에러인지도 몰랐다. 손버깅 할려다가 GDB로 보니 위의 메시지가 휘리링~~~)

아무리해도 고쳐지지가 않고, 책과 예제가 전혀 차이가 나는 부분이 없는데, 무엇이 문제일까 하다가 결국 .xib 파일이 문제라는 것을 알게 되었다.

코코아 프로그래밍의 경우, xib 를 이용하여 쉽게 프로그래밍을 할 수 있는데, 그 제약 사항이 많아서 보통은 .xib 를 쓰지 않는 형태로 코드를 작성하게 된다. 그런데 이 경우 –_-, .xib 에 기본 셋팅 정보가 들어있어서 이걸 지우지 않고 그냥 쓰게 되면, 해당 설정 정보와 현재 프로그램의 실행정보가 맞지 않아서 에러가 발생한다.

결국 가볍게 지워주니 한시간 넘게 삽질한 결과가 허무하게 잘 나온다.

이런 T.T 삽질의 황제가 되버렸군 T.T

iPhone 삽질기 – ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___

 iPhone 용 프로그램을 공부하다가 -_- 방금 ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___  이 에러 때문에 상당히 시간을 잡아먹었다. 역시 에러메시지에 답이 나오는데 삽질만 가득!!!

 

 결론은 이해력이 떨어지는가? 인가 -_-

 

Interface Builder 를 안쓰기 때문에 .xib 파일을 삭제했다. 그런데 Info.plist 에는 해당 Interface Builder에서 사용하는 정보가 남아있었던 것이다. 이로 인해서 시작시 .xib를 읽으려고 하고 거기에 없는 파일을 시작으로 넘겨줬기 때문에 에러가 발생한것 같다.

 

 이번 에러로 알게된것은 iPhone 어플이 실행될때, .xib 사용여부를 Info.plist 로 구분하는 거 같다라는 사실

 

흐음… 열심히 공부하자~~~ 

reentrant 와 thread-safe 는 다른 말이다

멀티 플랫폼을 대상으로 된 라이브러리를 MAC 용으로 포팅을 하다보니 신기한 문제를 발견했다.

 

MAC에서는 _r 계열 함수가 제대로 없는 것이다. _r 계열 함수는 reentrant 즉, 재진입 가능 함수를 의미한다.

 

착각하기 쉬운것이, thread-safe 하면 reentrant 하다고 생각하기가 쉬운데, 이 두개는 서로 다른 개념이다.

 

 즉 Thread-Safe 라는 것은 A,B 두개의 스레드가 strtok 같은 함수를 이용한다고 할 때,  각각의 스레드에서는 strtok가 호출될 때 문제가 없으면 된다. 보통 이럴 경우 내부적으로 해당 데이터를 TLS 에 넣어두면 thread-safe 하다고 볼 수 있다. 그런데 reentrant 할려고 한다면 문제가 발생할 수 있다.

 

 같은 스레드 안에서 strtok 가 두 번 불려진다면? 과연 다음과 같은 코드는 기대한 결과가 나올것인가?

 

  1. strtok(A, 어쩌구);
  2. strtok(B, 어쩌구);
  3. strtok( NULL, 어쩌구 );
  4. strtok( NULL, 어쩌구 );

 물론 위와 같은 형태로 바로 작성할 사람은 별로 없겠지만, Message 방식일 경우 가끔씩

위와 같은 문제가 발생할 수 가 있다. 그래서 strtok_r 같은 함수는 해당 결과를 가져올 수 있는 파라매터가 하나 더 있는 것이다. 즉, 몇번이고 strtok_r 이 불려지더라도, 원하던 결과로 동작할 수 있다.

 

 흐음, 그런데 MAC에는 왜 그 함수가 없었을 까? 함수명이 생각이 안난다. -_-