'objective c'에 해당되는 글 2건

  1. 2009.12.03 [iPhone App. 프로그래밍] Code 정리 기법
  2. 2009.11.29 iPhone 개발시 메모리 관리 지침!! (2)
2009. 12. 3. 23:34

[iPhone App. 프로그래밍] Code 정리 기법

가끔 생각날 때마다 이렇게 포스팅 할 생각입니다. 다음 편은 언제 올리느냐 라는 식의 기대가 있으면 좀더 자주 올릴수도 있겠으나... ^^ 독자가 적은 관계로 제 마음대로 올리고 싶을 때 올립니다.

Header파일에 넣어야 할 것들

1. importing할 해더 파일 들
 - 가급적 다른 해더 파일들을 import하지 않는 것이 좋습니다. 다른 class 정의를 가져 오고 싶을 때도 header파일을 가져오지 말고 @class를 이용해서 프로토타입만 정의하시기 바랍니다.
 - 프로젝트 전체적으로 사용하는 전역 해더 파일 (ex. debug, define, typedef 등이 정의되어 있는 해더 파일)은 권장합니다.

2. 사용할 class의 이름들
 - 단순히 class이름만 필요한 경우 @class를 이용하여 해당 이름이 class 이름이라는 것을 표시해둡니다.

3. class 정의
 - 상속받는 부모 class이름
 - delegate리스트는 부등호 사이에 넣어 줍니다. 수십개를 넣어도 괜찮은데 new line을 넣으면 안되는 것 같더군요. -_-;;
 - 사용할 변수를 중괄호 사이에 모두 넣습니다.
 - accessor함수들을 모두 정의합니다.
 - 외부에 노출할 인터페이스 함수들의 프로토타입들을 정의합니다.
 - 내부 함수는 여기에 정의하지 않는 것이 좋습니다. 내부 함수는 .m파일 내에 카테고리로서 따로 정의를 하면 깔끔하고 편리합니다. (뒤에 나옵니다.)

*accessor함수들을 정의할 때!!
 - 보통 포인트로 사용되는 녀석들은 retain키워드를 사용하여 자동으로 release되는 것을 막습니다.
 - string이나 변수들 중 값이 유지되어야 하는 변수들의 경우 copy 키워드를 이용하여 따로 메모리 영역을 운영하도록 합니다.
 - retain이나 copy를 사용하지 않으면 자동으로 assign이 됩니다.
 - 이렇게 정리된 accessor함수들을 모두 정의한 후에, class변수를 사용할 경우, 일관되게 self.변수이름 으로 사용하는 것을 습관화 합니다. 혼용해서 쓰다가 해깔립니다. 부득이한 경우(accessor를 정의하는 경우)를 제외하고는 모두 "self."를 붙이는 습관을 들입시다.

.m 파일에 들어가야 하는 것들
구현 파일에는 철저히 구현에 관련된 것들을 넣어야 합니다. 하지만 여러가지 종류가 있으니 확실히 구별하는 것이 소스를 읽을 때나, 확인할 때 시간을 절약해줍니다.
다시 한번 강조하지만, class변수들은 accessor함수를 사용하여 엑세스 하는 것을 습관화 합니다.



1. 우선 필요한 해더 파일을 모두 import합니다.
2. 매우 유용한 팁!! 바로 카테고리 입니다. 해당 클래스의 PRIVATE카테고리를 이곳에 정의합니다.
이렇게 함으로써 좋은 점은 이후의 코드에서 사용자가 정의한 함수들에 대해서 scope에 영향없이 마음대로 쓸 수 있다는 장점이 있습니다. 또한, 사용자가 정의한 함수 이면서 내부에서만 사용하는 함수가 무엇인지 한눈에 볼 수 있어 무척 편리한 기법입니다.
(C언어로 프로그래밍을 해본 분들은 아마 이 코드만 봐도 흐믓해하지 않을까요?? 저는 이 방식을 발견하고 나서 무척 기분이 좋았습니다..^^;)

3. 이 이후에는 함수 정의를 합니다. 그런데 한가지 생각해야할 것은 수 많은 delegate함수가 있다는 점입니다. 또한, 몇몇 delegate는 delegate를 따로 정의하지 않아도 delegate인 경우도 있습니다. 그리고 위에서 정의한 내부에서만 사용하는 사용자 정의 함수도 있지만, 외부에서 사용하는 사용자 정의 함수(header파일에서 정의한..)도 있습니다. 그러므로, 각 함수들 사이에 구분을 해주는 주석을 넣어줘서 정리하면 가독성이 한층 좋아집니다.

다음은 제가 사용하는 구분용 주석입니다.
//------------------------------------------------------------------------------------
// TextView delegate



Trackback 0 Comment 0
2009. 11. 29. 15:58

iPhone 개발시 메모리 관리 지침!!

C언어 계열 프로그래밍을 할 때 가장 중요한 것 중에 하나가 바로 메모리 관리입니다.
C언어는 당연히 그렇고 C++ 역시 다르지 않습니다. C언어로 부터 파생된 Object-C의 경우 두말할 필요 없겠지요?

C언어의 경우 매우 명확한 메모리 관리 기법을 제공합니다.
메모리 생성은 alloc계열 함수(alloc, malloc, calloc)로 하고, 자신이 alloc한 함수는 어떤 경우든, free를 호출해서 해제해야만 메모리 릭이 발생하지 않습니다.

그렇다면 iPhone에서의 Object-C는 어떨까요?
다음의 말을 기억해야 합니다.
"자신이 생성한 메모리는 자신이 release해야만 한다", 그러나, "자신이 생성하지 않은 메모리는 release해서는 안된다"
매우 명확해 보이기는 하지만, 실제로 프로그램하다보면 쉽지 않다는 것을 알 수 있습니다.
그 이유는 C언어에는 없는 retain개념과 autorelease개념이 있기 때문입니다.

1. 자신이 할당한 메모리란 무엇인가?
간단하게 자신이 할당한 메모리는 다음의 이름이 들어간 함수를 호출한 경우입니다.
new
alloc
retain
copy

2. 자신이 할당하지 않은 메모리란 무엇인가?
1번에서 말한 함수 이외에 CLASS에서 제공하는 constructor에 의해서 제공되는 메모리입니다. 예를 들면 다음과 같은 것들이지요
UIImage *newImage = [UIImage imagenamed:@"abcd.png"];

이 경우에는 자동으로 autolease pool에 들어가게 되어서 언제든 자동으로 해제되게 됩니다.

그러나, 1번에서 말한 것 같이 retain함수에 의해서 메모리에 대한 소유권을 취득한 경우, 자동으로 해제되지 않습니다. 코드로 보자면 이렇지요
UIImage *newImage = [[UIImage imagenamed:@"abcd.png"] retain];

그리고 한가지 더!!
1번에서와 같은 함수를 써서 메모리를 할당하더라도 강제로 autorelease함수를 부른 경우, 자동으로 메모리가 해제되므로 release함수를 부르는 경우, 프로그램이 마구 죽습니다!!
UIView *newView = [[[UIView alloc] initWithFrame:CGRectMake( x, y, width, height)] autorelease];
마구 죽는 이유는 위와 같이 함수를 호출 한 후,
[newView release];
를 호출하면, 바로 죽지 않고, 시스템에서 해당 메모리를 자동으로 해제하기 위해서 autorelease pool에서 해당 메모리 값에 대해서 rereleae를 호출합니다. 그 순간 프로그램은 DIE~~~~!!
이렇게 강조하는 이유는, 디버거로는 죽는 이유를 잡는 것이 거의 불가능에 가깝기 때문입니다. 이런 문제가 발생하기 시작하면, 프로젝트 기간이 길어지거나, 심한 경우 처음부터 다시해야 하는 상황이 발생하기 때문입니다.

3. retain이란 무엇인가?
C언어에서는 메모리에 대한 소유권에 대한 개념이 약합니다. 메모리에 대해서 한 곳에서 alloc을 한 경우, 그냥 free하면 됩니다만, 이런 경우, 똑같은 내용을 사용하고자 하는 경우 동일한 형태의 변수에 대해서 alloc하거나 free를 조건부로 해야 하는 경우가 생깁니다.
이러한 불편함을 없에고, 좀더 캡술화된 구현을 위해서 retain count라는 것을 사용합니다.
즉, memory공간에 대해서 해당 메모리 영역을 사용하는 코드의 개수를 써 놓는 것입니다. 예를 들어서,
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake( x, y, width, height)];
이 경우 newView에 대한 retain count가 1입니다. 그런데, 다른 영역에서 이를 사용하기 위해서 retain을 한 경우
UIView *duplicatedView = [newView retain];
newView의 retain count 는 2가 됩니다. 다시 여기에서
[newView release];
를 해도 retain count가 1이 되므로 실제적으로는 메모리가 해제되지 않습니다.

이러한 기법은 너무나 많이 사용됩니다. 예를 들면 다음과 같습니다.
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake( x, y, width, height)];
[currentViewController setView:newView];
[newView release];
위 코드는 일반적으로 view를 생성해서 viewController에 view로서 대입하는 코드 입니다. 앞에서 설명한 것과 같이 newView에 메모리를 할당한 후, 마지막에 release를 했습니다. 그럼에도 불구하고 이 코드가 정상적으로 작동하는 이유는 setView를 하는 함수내에서 retain을 하기 때문입니다.

4. autorelease의 사용은 조심해서 해야 한다.
autorelease는 할당한 메모리를 자동으로 해제하는 코드입니다. 기본적으로 autorelease는 한번실행되는 시레드 상에서는 해제되지 않는다고 생각하시면 됩니다. 그러나, 코드가 끝나고 제어를 시스템에 넘긴 상태에서는 언제든 해제될 수 있으니 왠만하면 alloc, release루틴을 사용하는 것이 좋습니다.
그럼에도 불구하고 너무나 편리한 함수이므로 다음과 같은 상황에서 사용하면 좋을 것입니다.
 - 특정 함수내에서 메모리를 할당해서 리턴해야 하는 경우
 - 메모리가 재 사용될 가능성이 있는 코드
(더 많은 사용처가 있을 것 같지만, 제 경우 위의 두 가지에서만 사용합니다.)

4.1 특정 함수내에서 메모리를 할당해서 리턴하는 경우
예를 들어서, 특정 함수를 부르면 자동으로 view를 생성해서 모든 기본 설정을 완료하면 좋겠다라고 생각하는 경우 추가적은 subclass를 만드는 것보다 간단하게 함수로 만드는 것이 편리할 것입니다.
- (UIVIew *) createBasicViewWithFrame:(CGRect)rect
{
UIView *newView = [[[UIView alloc] initwithFrame:rect] autorelease];
/* 그외 여러가지 설정 들...*/

return newView;
}

이렇게 함수를 작성한 경우, 리턴된 값에 대해서 release함수를 따로 부르지 않아도 된다는 장점이 있습니다. 만약 이를 C언어 코드로 바꾼다면 함수 밖에서 메모리를 할당하고 함수를 부를때, call by reference로 전달한후, setting이 완료되면 사용 후, free를 해줘야 합니다만, 위와 같이 하면 함수안에서 모든 것이 해결되니 편리합니다.

4.2 메모리가 재 사용될 가능성이 있는 코드
이는, 사용자 코드가 아닌 시스템 코드에서 제공하는 경우가 있습니다 대표적인 예가 UITableViewCell이 경우입니다.
MEListCellThumb *cell = (MEListCellThumb *)[tableView dequeueReusableCellWithIdentifier:thumbCellIdentifier];
if (cell == nil)
{
            [[NSBundle mainBundle] loadNibNamed:@"MEListCellThumb" owner:self options:nil];
}

5. 그외 주의할 점.
iPhoneOS 3.0이 된 이후에 setValue함수 설정에 retain을 하는 경우가 많이 있습니다. 그러므로 accessor함수를 호출할 때는 언제나 자동으로 retain이 되는 것으로 생각해야 합니다. 그러므로 자신이 짜는 코드내에서 변수를 직접 억세스 할 것인지 accessor함수를 쓸 것인지 통일해서 사용하는 것이 실수를 줄이는 방법입니다.


자세한 사항은 다음 문서를 참고하세요
iPhone프로그램을 원활히 하고자 한다면 다음의 문서를 3번 정독하기를 추천합니다.
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

Trackback 0 Comment 2
  1. Favicon of https://enigmasi.tistory.com BlogIcon enigmasi 2009.12.03 13:24 신고 address edit & del reply

    그래..갠적으로 오브젝티브씨하면서
    그 많은 [] 들 때문에 당황되고, 메모리관리때문에 쓰러질 지경이었는데. 요즘은 나름 정리가 좀 되는 기분...ㅎㅎ
    낼롬 퍼가야지...근데 어떻게 하는거지..

    • Favicon of https://implement.tistory.com BlogIcon 열야 2009.12.03 19:32 신고 address edit & del

      뭔소리야.. 나보다 잘하면서..ㅡ.ㅡ