특정 view에서는 default인 회색바가 아닌 검정색 bar나 투명한 검정색을 쓸 경우가 있다 (아이팟이나, Photo app처럼)

그럴 경우, UIView class에서 viewWillAppear를 override하고, 그 안에 아래의 code를 넣어주면 된다. 
한번 로드하고 안바꿀꺼라면 viewDidLoad에서 해도 되고...

[[UIApplication sharedApplicationsetStatusBarStyleUIStatusBarStyleBlackOpaque];

위의 코드는 검정색 bar로 만든다 (ipod처럼) 마지막 상수를 바꾸면 반투명 검정색 bar로 바꿀 수도 있다


Posted by yunseong

이미지 뒤집기를 할 때 UIImageView를 이용할 수 있다면, 매우 쉽게 해결할 수 있다. 

UIImage* artworkImage = [UIImage imageNamed:imageUrl];


[artworkReversedView setImage:artworkImage];

artworkReversedView.transform = CGAffineTransformMakeScale(1, -1);

위의 경우는 수평으로 뒤집기 (horizontal) 

CGAffineTransformMakeScale의 두 상수값을 조절하여 뒤집는 방향을 조절할 수 있다.
Posted by yunseong

Keyboard를 activate시키는 어떤 control이 firstResponder가 되면 keyboard는 자동으로 올라온다. 해당 control을 firstResponder가 아니게 만들면 keyboard는 사라진다. 

-(IBAction) editnigDone: (id)sender {
[sender resignFirstResponder];
}

예를 들면 UITextField는 Did End OnExit event를 위의 코드에 연결해주면 된다.

그런데 UITextView는 어떤 이벤트에 엮어야 하는거야 -_-;;


Posted by yunseong

Objective-C 2.0에서는 Retain count 기반으로 메모리 할당 해제가 관리 됩니다. 
그 규칙은 다음의 3가지 입니다. (Apple의 Memory Management Programming Guide for Cocoa 참조)

 
1. You own any object you create. (니가 만든건 니가 갖는다)
    You "create" an object using a method whose name begin with "alloc" or "new" or contains "copy" (for example, alloc, newObject, or mutableCopy).

2. If you own an object, you are responsible for relinquishing ownership when you have finished with it. (만약 객체를 소유했으면, 다 쓸때 반환하는 것에 대한 책임도 가지게 된다)
    One way to relinquish ownership of an object is to send it a release message, In cocoa terminology, relinquishing ownership of an object is typically referred to as "releasing" an object.

3. If you do now own an object, you must not release it. (직접 만든 객체가 아니면 절대 해제하지 마라)


규칙은 간단합니다. 만든건 책임지고, 안만든건 건드리지 말라. Memory leak을 유발하지 않기 위한 가장 기본적인 원리입니다. 

위의 규칙을 몸소 겪어보고자, 요 한동안 삽질의 연속이었습니다. Retain / Release를 통한 메모리 관리 mechanism을 몸에 베게 하기 위해 일부러 NSAutoreleasePool 객체를 만들지 않고 코딩연습을 했습니다. 그렇게 하면 정확한 프로그래밍을 하지 않으면 leak이 우수수 쏟아질 것으로 생각했기 때문입니다. (그러나 convenience method를 호출할 수 없어 난관이 있었습니다 -_-;)

머 결과는 그닥 보잘것이 없습니다. Web에서 쉽게 찾아볼 수 있는 수준의 결과가 나왔네요. 몇일 동안의 삽질 끝에 알아낸 것을 정리합니다. 

1. NSString에서 initWithXXXX계열의 함수들은 parameter로 받은 객체의 retain count를 1 증가시킨다.
즉 복사가 아닌 reference한다. 사실은 initWithXXXX계열의 함수는 alloc된 객체에 의해서만 가능합니다. 즉, alloc을 호출하기 때문에  retain count가 증가하는 것은 당연한거지요. 이 말은 즉, 직접 release까지 해 주어야 한다는 것입니다.  

2. NSString에서  stringWithXXXX계열의 함수들은 parameter로 받은 객체를 "복사"하고 NSAutoreleasePool에 등록한다.
 즉 객체를 만든 입장에서는 release를 해주지 않아도 된다는 것입니다. 이 함수는 alloc을 호출하지 않고 [NSString stringWithFormat: ~~~] 이런 형식이기 때문에 alloc을 사용자가 명시적으로 호출하지 않습니다. 즉 release하지 않아도 된다는 것입니다. AutoreleasePool을 이용한 release는 delayed release가 됩니다.  이런 stringWithXXXX같이, 사용자가 release를 신경쓰지 않고 autoreleasePool을 이용하도록 하는 함수를 Convenience Method라고 합니다. 

3. Code상에 @"ABCDEF"같이 문자열을 직접 쓰는 것은 객체가 아니기 때문에 해제할 필요도 없다. 문자열을 이용해 initWithString함수를 이용해 만든 NSString객체는 해재할 필요 없다. 

그런데!!! 참 알다가도 모르겠습니다. main함수에서 열심히 retain counter를 올려봤건만... 하나도 release하지 않았는데 프로그램이 종료될 때 까지 leak error가 발생하지 않더군요... 이건 참 모르겠습니다. 물어볼 사람도 없는데 -_-;;
 

#import <Foundation/Foundation.h>

#import "Test.h"


#import <Foundation/Foundation.h>

#import "Test.h"


int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool allocinit];

    Test* test = [[Test allocinit];

    [test printMemberRetainCount];


    NSString* testName = [NSString stringWithFormat@"ABCDEFG"];

    [test setName: testName];

    [test printMemberRetainCount];

    
    [testName
retain];

    NSLog(@"Test Name's retain Count : %d", [testName retainCount]);

    [pool drain];

    

    return 0;

}



저 녹색 글씨부분... 분명히 retain Counter가 1 증가하여 autoreleasePool에서 release시켜도 dealloc안되고 leak이 되어야 하는데... 



어디에도  leak에 대한 error는 없습니다. -_-;; 모르겠네요 -_-


Posted by yunseong
이제 실제 XCode에서 버젼관리가 되는 개발을 시작해보겠습니다. 

원본소스를 이용해 소스코드를 import시켰지만, 정작 원본소스 코드를 XCode로 여시면, version관리가 되지 않습니다. Repository에서 새로 코드를 받아서 열어야만, 버젼 관리가 됩니다. 

Repository explore에서 trunk폴더를 선택하시고, 프로젝트 폴더를 선택하시고, Check Out버튼을 누릅니다. (물론 원본소스코드와 다른 폴더이여야 겠죠? 아니면 원본폴더를 지워버리셔도 됩니다. 어짜피 서버에 있으니까...)


Check Out이 끝나면, 

이런 창이 뜨고, project를 Open합니다. 

열린 프로젝트 창에서 File Name이라고 써 있는 부분에서 마우스 오른쪽 click을 하시면, 다음과 같이 SCM항목이 나옵니다. 여기서 SCM을 체크해줍니다. 

바로 소스의 변경 상태를 나타내주는 column입니다. 간단히 소스코드를 수정해보면, 

contact.m 파일 옆에 M(Modified) 이라고 나타납니다.  다른 사람에 의해 Upload된 파일이 있으면 U라고 뜹니다. (근데 google은 좀 반응이 느리군요 -_-)

수정내용을 repository에 반영하려면, 아래와 같이 Commit Changes, 혹은 rollback하려면 Discard Changes를 선택하시면 됩니다. 

Commit을 하시면, 이 코드에 대해서는 Revision이 1 증가하게 됩니다. 

아래의 2개의 캡쳐를 비교해 보시면, 
위의 그림이 Commit하기 전, 

이게 방금 Commit한 캡쳐입니다. revision이 r2에서 r3로 증가했습니다. 

우선 저도 해본게 여기까지라 당장은 더이상의 posting이 어렵군요 -_-;;
여기까지는 SVN의 가장 기본적인 기능입니다. 물론 실제 project를 진행하려면, rollback도 할 줄 알아야 하고, Diff툴도 쓸 줄 알아야 하고, 다른 revision끼리의 merge도 할 줄 알아야 하는데, 저는 아직 SVN은 익숙치가 않네요 ^^;

사실 이런 SCM 시스템이 있어도, 적절한 branch전략, labeling (tag생성), 그리고 merge가 뒷받침되지 않으면 안됩니다. 회사에서 Clear Case를 쓰는데, 그런 비싼 고가의 tool이 있어도 그냥 대충 쓰는 사람이 있는가하면 끝내주게 체계적으로 사용하는 사람도 있습니다. 

각설하고, 나중에 merge, rollback등이 익숙해지면, 또 posting 해야 겠습니다. 



Posted by yunseong
먼저 XCode에서 개발하고자 하는 project를 생성합니다.

그리고 project가 생성된 폴더를 보면 아래와 같이 xcodeproj파일 및 pch, h, m파일 등이 있을 것입니다. (저는 console기반의 project를 만들었고, 이미 몇 개의 파일을 만들어 놓았습니다.)

이 파일들을 repository에 올릴텐데, 이 때 이 폴더에 있는 모든 파일을 올릴 필요는 없습니다. 
이 중에 개발산출물 폴더인 build폴더, 그리고 프로젝트 파일을 가장한 폴더인 xcodeproj안의 mode 파일, pbxuser파일은 굳이 공유할 필요도 없고, 버젼관리가 될 필요가 없습니다. 오히려 이 것들이 version tree안에 있으면, merge나 check in시에 귀찮기만 하지요. 그래서 이 것들을 알아서 빼도록 설정합니다. 

터미널을 띄우시고, 
cd ~/.subversion 폴더 안의 config파일을 수정합니다. 

수정 내용은 global-ignore라는 항목을 찾아서 (아래 검정색 박스로 만들어 놓은 부분입니다)
 
다음과 같이 수정합니다. 

맨 앞에 '#' 을 지워 주석처리를 없애주시고, 뒤에 "build *.pbxuser *.mode*" 라고 추가하고 저장합니다. 의미는 집작하셨겠지만, 여기에 해당하는 파일들은 repository에  upload할 때 자동으로 빠지게 됩니다. 

그리고 실제 upload를 해 봅시다

XCode에서 SCM --> Repositories... 를 선택하시면, 

이 창이 뜨는데, 만든 Repository를 선택하시고, trunk 폴더를 선택합니다. 아시다시피 trunk폴더는 main소스코드가 저장되는 곳이기 때문에... (저는 이번에 알았습니다 -_-)
trunk 폴더를 선택하시고, 왼쪽 상단의 Import 버튼을 누르면, 

창이 뜹니다. 여기서 프로젝트 폴더를 선택하시고, 아래의 comment box에 간단한 Comment를 달고 Import 시킵니다. 

그럼 잠시후에 Import Completed라는 메시지 박스가 뜹니다. 

그리고 trunk 폴더를 확인해보면, 

소스코드가 repository에 upload되었습니다. 그리고 불필요한 파일인 mode, pbxuser 파일, Build폴더 등은 없습니다. 이렇게 하면 기본적인 Upload는 다 되었습니다. 

다음 Post는 이제 repository에서 소스코드를 다운받고, 버젼관리하는 것을 보겠습니다. 

참고로, 이 내용은 박진형님의 blog내용을 참조했습니다 (http://jinhyung.org/2008/06/04/inside-xcode-1/
Posted by yunseong
Google Project Hosting site에서 Project생성을 완료했으면, XCode에서 연결을 해야겠죠. 

XCode를 실행시키면 menu-bar에서 SCM --> Configure SCM Repositories... 를 선택합니다. 


처음 SCM을 셋팅하신다면, Repository가 아무것도 없을거고, 이미 있으시다면 있겠죠 -_-;; 

제 캡쳐화면엔 있지만, 새로 셋팅하는 것으로 하겠습니다.

먼저 왼쪽 하단에 + 표시를 누르시면, 

요렇게 뜹니다. 이름을 입력해주시고, SCM System은 Subversion을 선택합니다. 

그러면 Subversion Setting창이 뜹니다. 정보를 입력해줘야 하는데, 

먼저 URL은 google Project hosting에서 앞장에서 만든 Project 메인페이지에서 "Source" tab을 클릭합니다. 


선택하면, 

자, 화면 중반부에, https 프로토콜의 URL을 볼 수 있습니다. 여기서, trunk 앞, 즉 ~~~~~/svn/ 까지를 복사해서 XCode의 URL창에 붙여 넣습니다. 

그리고 URL에서 focus를 out시키면, Scheme, Host, Path창이 자동으로 입력되고, SSL Certificate 창이 뜹니다.  Accept하시고, 

username은 본인의 google ID (@gmail.com은 뺍니다) 를 입력하고 (만약 제 Id처럼 .이 있으면 .은 빼고 입력합니다) Password는 화면 중반부의

When prompted, enter your generated googlecode.com password.

에서 링크된 부분을 클릭하면 Password가 나옵니다. 

역시 입력을 마치시고 apply를 누르시면

아래와 같이 "Authenticated"가 떠야 합니다. 떴으면 인증 완료입니다.



그럼 생성된 폴더를 확인해봅시다.

XCode메뉴의 SCM --> Repositories... 를 선택하면 Repositories창이 뜹니다. 


거기서 왼쪽에 방금 만든 Repository를 선택하면

보시는 것과 같이 SVN의 기본 폴더인 trunk, branches, tags 폴더를 보실 수 있습니다. 

우선 연결은 이렇게 하면 끝나겠네요. 다음은 실제 XCode Project를 설정하고, source code를 올리는 것을 posting하겠습니다. 




Posted by yunseong
SVN서버는 SCM (Software Configuration Management, 소프트웨어 형상 관리) tool 중 하나로, CVS의 개량판이라고 하더군요. 사실 저희 회사는 IBM社의 Clear Case를 쓰기 때문에, SVN은 이번에 처음 써봤습니다. CC와는 다른 부분이 많아서 아직도 햇갈리는 부분이 많지만, 머 차차 적응해가야 겠지요 ^^

요새 집에서 iPhone S/W를 개발해보려고 하고 있는데, source code version을 관리할 마땅한 시스템을 찾지 못하고 있었습니다 (회사의 CC는 외부에서 접속 불가 -_-, 게다가 XCode는 CC지원 안함 -_-) . 리눅스도 잘 쓸줄 모르고, 집에 있는 데탑에 WinCVS서버 깔면, 항상 집에 있는 PC를 켜놔야 하고...(요새 경제가 어려워 전기료가... -_-). 무엇보다 저는 PC를 자주 포맷하는 편이라 안정적으로 서비스를 제공하는 사이트를 찾아야 했습니다. 이를 찾기 위해 웹검색을 한 결과 역시 google은 에지간한 서비스는 다 하고 있더군요. 물론 assembla나 다른 몇개의 사이트도 찾았지만 아무래도 google이 안정적일 것 같아 google로 결정했습니다. 단!! google은 open source를 전제로 한다는 것!! 누구나 source code를  browsing할 수 있습니다.  저는 제 소스를 많이 부끄러워하는 편이라 공개하는건 좀 그렇지만, 아직 본격적인 개발을 할 단계는 아니고, SVN에 익숙해질 겸, Objective-C에 익숙해질 겸 해서 우선 여기에 둥지를 틀기로 했습니다. 그럼 시작합니다!!

먼저 http://code.google.com에  로긴해서 Project Hosting --> create new project를 클릭하여 기본적인 프로젝트 정보를 입력하여 프로젝트를 생성합니다. License종류를 선택하라는데, 이 부분은 저는 머가 먼지 몰라서 아무거나 선택했습니다. 차이점을 아시는 분은 답글 달아주시면 감사하겠습니다. (제가 linux를 모르니 이런 부분은 상당히 약하군요)



project를 다 만들었으면, 화면 오른쪽 상단에 Profile을 클릭하면 본인이 만든 프로젝트가 나옵니다. 그럼 우선 project는 생성 끝입니다 -_-;;

참고로 이 Google Project Hosting은 SVN뿐만 아니라, wiki, DTS (Defect Tracking System) 까지 지원을 해줍니다. google doc까지 쓰면 Project관리의 상당부분을 One-Stop으로 관리할 수 있습니다.
Posted by yunseong
NSString 객체를 만들 때, 참 햇갈리는게 있더군요 -_-;;

한동안 MFC와 C언어만 하다보니, java같은 개념은 다 까먹은 듯 합니다 ㅠㅠ

어쩄든 오늘 삽질 한 결과는 다음과 같습니다.

1. @"abcde" 이렇게 상수형 문자열은 객체가 아니기 때문에 retain count가 없습니다. 없는 건 아니고 쓰레기값...
2. XXXWithString 계열의 함수는 parameter로 입력된 NSString객체를 참조합니다. 즉 2개의 포인터가 하나의 객체를 보게 되어 parameter로 입력된 NSString 객체는 retain count가 1 증가하게 됩니다.
3. XXXWithFormat 계열의 함수는 parameter로 입력된 NSString객체의 값을 복사합니다. 즉 parameter로 입력된 NSString객체의 retain count는 변화가 없으며, 새로운 객체가 생성되는 것 입니다.

오늘 몇시간 동안 삽질해서 알게 된 내용이네요 -_-;;;



080815 수정
StringWithFormat함수는 내부적으로 autorelease pool을 사용하는 것 같습니다. autorelease pool을 만들지 않은 상태에서 호출하면 error가 발생하는 군요. 그 말은 임시 NSString 객체를 만들 때 메모라 할당과 해제를 신경쓰지 않아도 된다는 것인데... iPhone 프로그래밍에서는 못써먹는 건가 봅니다 -_-;;
Posted by yunseong

머 제목은 매우 거창합니다만 ㅡㅡ;;

Cocoa framework의 Objective-C는 C와는 다른 메모리 관리 mechanism을 가지고 있습니다.
바로 retain / release를 통한 메모리 관리인데요, 쉽게 말하면 reference count를 통해
메모리를 해제할 지 말지를 결정하는 것입니다.

예전에 학교 다닐때 memory leak관련해서 연구할 때 이거와 관련된 내용을 공부한 적이 있는데,
실제 이 방식으로 동작하는 언어가 있는 줄은 몰랐네요.

어쨌든 오늘 이 내용을 공부도 하고 이것저것 실험도 해봤는데요, 사실 엄청나게 삽질을 했습니다.

다름이 아니라 NSString 객체를 이용하여 테스트 했는데, NSString객체도 잘 모르는 상태에서
이것저것 하다 보니 완전 삽질만 했습니다.

어쨌든 내린 결론은, Release도 함부로 하면 안된다는 것입니다. ㅡㅡ;;

NSObject의 dealloc을 override하여 사용해 봤는데, 멤버 변수를 dealloc에서 release시키면,
main함수의 AutoReleasePool이 drain할 때 오류가 발생하더군요.
모든 멤버변수는 dealloc내의 super dealloc에서 모두 알아서 release하나 봅니다.

물론 자체적으로 release시키고, nil로 값을 셋팅해주면 nil은 super dealloc에서 호출되는 release를 무시할 것이기
때문에, 큰 문제는 없어보이겠지만, nil에 message를 던지는 것은 가급적 피하려고 하고 있습니다. 나중에 bug를 만들어낼 거 같아서요.

어쨌든!!!
아무리 dealloc을 override했어도, 멤버변수가 가리키는 객체는 강제로 release시키지 말자는 게 오늘의 교훈이었습니다. 근데 맞나 모르겠네요 -_-;;;
Posted by yunseong
이전버튼 1 2 이전버튼