'프로그래밍/Mac'에 해당되는 글 4건

앞장에 이어 오프젝트C를 설명한다.

 

----------------------------------------------------------------------------------------

동적 타이핑, 동적바인딩

 설명에 들어가기에 앞서 id형에 대한 이야기를 해보려 한다.

 

우리에게 어떤 클래스 두개가 있다고하자 (일단 C++문법으로)

이 두개의 클래스는 RPG게임에서 화면상에 배열로 저장된 맵에

그려질 캐릭터 객체이다.

class Swordman

{

 int x,y;

 image *p;

 int hp, mp;

 (void)printOut(void)

 {

   drawImage(x,y);

 }

}

 

class Cleric

{

 int x, y;

 image *p;

 int hp, mp;

 (void)printOut(void)

 {

   drawImage(x,y);

 }

}

 

이것을 객체로 만들면

Swordman *sword = new Swordman;

Cleric *clerics = new Cleric;

이다

위의 그림은 맵인데 총 7 X 5의 크기이다.

배열 array[7][5]에는 무슨 캐릭터가 있는지에 대한 값이 저장되어 있는데

0이면 없고, 1이면 검사, 2면 성직자가 있다고 한다.

일단 여기 배열에 다음과 같이 값이 저장되어있다고 하자

 

여기에 난 for문을 사용하여 모든 맵 타일에 캐릭터들을 그리려 한다.

그렇다면 내가 생각할 수 있는 제일 편리한 방법은 이런 방법일 것이다.

for(i = 0 ; i < 7 ; i++)

{

  for( j = 0 ; j < 5 ; j++)

    array[i][j]->printOut;

}

이런식으로 되야 가독성도 높고 코드를 읽는 사람이 편하게 읽을 수 있다.

하지만 캐릭터 클래스가 2개가 있으므로

배열에 타입이 다른 클래스를 저장한다는건 불가능하다.

왜냐하면 애초부터

 

Swordman *array[7][5] 라고 배열을 선언해놓고 array에 값을 넣을때

array[3][3] = clerics;

 

성직자 객체를 저장할수가 없다.

 

타입이 다르기 때문이다. 하지만 Objective C에는

ID타입이 있는데 이것은 C++에 void타입과 비슷하다.

id array[7][5]로 선언하면

 

array[3][3] = clerics;

array[2][2] = sword;

로 다른타입의 객체를 저장할수가 있다.

이렇게 되면

 

for(i = 0 ; i < 7 ; i++)

{

  for( j = 0 ; j < 5 ; j++)

    array[i][j]->printOut;

}

이런 주문도 가능하다는 것이다. ID 설명은 여기까지..

그럼 동적타이핑과 동적바인딩에 대한 설명을 하겠다.

 

동적 타이핑

 

 동적 타이핑을 이해하려면 오히려 정적 타이핑개념을 이해하면 된다.

id는 모든 데이터형을 저장할 수 있다. 그렇다면 id 만 쓰면 되지 어렵게 여러가지 데이터형을 쓸까?

답은 메모리 때문이다. 메모리를 절약하기위해 특정 테이터형을 명시하는 것이다. 이것을 정적 타이핑이라고 한다. 이와 반대되는 개념이 동적 타이핑이다. 즉 특정 객체의 데이터형을 런타임시에 파악하는 것을 이야기한다.

 
동적 바인딩
 

동적바인딩은 객체에 호출되는 실제 메서드를 알아내는 시기를 프로그램 실행 중으로 미룬다.

메소드 판단을 런타임에 한다는 점에서는 다형성과 같지만 동적 바인딩은 id 와 관련된 개념이다.

다음을 보자

 

id dataValue;

Fraction *f1; // Fraction : 분수 클래스

Complex *c1; // Complex : 복소수 클래스

dataValue = f1;

[dataValue print];

dataValue =c1;

[dataValue print];

 

dataValue print 에서 프로그램은 컴파일시에 Fraction의 Print를 할지 complex의 print를 할지 알수 없다. 런타임시에 객체의 클래스가 무엇인지 알아낸다.

 

Cat *cat = [[Cat alloc]init];

[cat sing] // 컴파일시에 경고

id cat = [[Cat alloc]init];

[cat sing] // 컴파일시에 경고 안함. 런타임시에 경고

 

-------------------------------------------------------------------------------------------

 

카테고리

 

 아까 언급했던 캐릭터 클래스 중에 Swordman 클래스를 예로 들어보자

아까는 C++로 표기했지만 이번에는 ObjectiveC로 쓰겠다

 

@interface Swordman:NSObject

{

  int x, y;

  image *p;

  int hp,mp;

}

-(void)printOut(void)

 

@implementation Swordman

-(void)printOut(void)

{

  [mFrame drawImage: p];

}

 

기존 구현은 이렇게 되어 있는데..

만약에 내가 소드맨을 그리는 것 말고 소드맨의 상태이상을 조종하는 메소드들을 추가하고 싶다면?

"그러면 그냥 클래스 안에 메소드를 써넣으면 되잖아!"

 

물론 그말이 맞다. 근데 이 클래스에 구현될 메소드 들을 여러 프로그래머랑 같이 작업하는

것이라서 함부로 건드릴수 없다면?

 

 이런 상황에서 ObjectiveC는 카테고리를 쓰길 권장한다.

방법은 다음과 같다. 기존 구현부분은 냅두고 추가로

 

@interface Swordman (statusControl)

-(void)Bleeding(void);

-(void)Healing(void);

-(void)Poisened(void);

-(void)Paralize(void);

 

@implementation Swordman (statusControl)

-(void)Bleeding(void)

{

 //구현부분

}

.

.

 

이렇게 따로 추가해주면

statusControl이라는 카테고리로 기존 Swordman클래스에 저 메소드 들이 추가가 된다

하지만 남용하면 위험하니 충분히 다른 사용 예를 검토하고 쓰길 바란다.

카테고리는 여기까지..

 

프로토콜

 

프로토콜에 대해 설명하겠다.

프로토콜(protocol).. 사전식 풀이로는, 규범, 규칙이다.

 

 프로토콜은 여러사람들이 한가지 프로젝트를 할 때 유용한 개념이다.

위에서 우리는 ID타입에 대한 개념을 봤었다.

 

ID타입을 통해 printOut으로 캐릭터를 출력했었는데,

만약 사람들이 각자 다른 직업의 클래스를 만든다고 하자

소드맨,클레릭,엘프,드워프

 

근데 각자 클래스마다 출력하는 메소드가 다르다면?

 

소드맨.printOut

클레릭.printChar

엘프.printElf

드워프.printDwarf

 

이러면 아무리 유연한 ID타입형 배열에 저 객체들을 집어 넣어도

printOut을 하면 소드맨만 출력되고 나머지는 메소드명이 틀렸다고 에러가 뜰 것이다.

 

물론 프로그래머들 끼리 모여서 메소드명을 통일하기로 정한 후에 하면 저런 문제는

발생할 가능성이 적어지겠지만, 그래도 누가 실수안할거라고 확신할수 있을까?

 

 이런 상황에서 프로토콜은 클래스에 어떤 지켜야할 "규정"을 정해줌으로서

저런 상황의 발생을 줄일 수 있도록 해준다.

 

 프로그래머들 끼리 캐릭터출력하는 것을 printOut으로 정했다고 하자.

이 규정을 프로그램에서 프로토콜로 표현하면

 

@protocol printProtocol

- (void) printOut (void)

@end

 

이다.

 

 이제 각자 클래스를 만들때

뒤에 <프로토콜명>을 명시하면

 

@interface Swordman:NSObject <printProtocol>

 

클래스에 -(void) printOut (void) 메소드가 구현이 되어 있지 않으면

컴파일러가 오류로 처리하고, printOut을 클래스에 구현할 것을 명령한다.

 

 인수와 메소드 이름, 리턴 타입도 전부 동일해야만 한다.

@interface Dwarf:NSObject <printProtocol>

{

  int x, y;

  image *p;

  int hp,mp;

}

-(void)printDwarf(void)  

 

@implementation Swordman

-(void)printDwarf(void)

{

  [mFrame drawImage: p];

}

//프로토콜에 규정된 printOut 메소드가 없으므로 컴파일러는 오류로 처리한다.

//printDwarf를 규정되어 있는 printOut으로 바꿔야 그제서야 컴파일러가 넘어간다.

 

-----------------------------------------------------------------------------------------

 

Foundation Framework

 

 이제 나오는 것들은 Objective C에서 제공해주는 프레임워크들에 대한 내용이다.

Foundation 프레임워크는 WinAPI와 비슷하다고 보면 된다. 프로그래밍에서 쓰이는

유용한 메소드들을 모아놓은 것인데

 메모리 관련 메소드

 숫자 관리 메소드

 파일관리 메소드

 기타 등이 있다.

  대표적인 것들만 다루고, 더 궁금한게 있다면 검색해보길 권한다.

그만큼 내용도 많고, 찾아서 쓰기만 하면 되는 것들이기 때문에 많이 다루지는 않겠다.

 

 NSNumber

 

 정수,실수,복소수, 심지어 문자도 가리지 않고 저장이 가능하다.

 관련 메소드는

 initWithChar : 문자형 객체로 초기화한다.

 initWithInteger : 정수형 객체로 초기화한다.

 initWithFloat : 실수형 객체로 초기화 한다.

 

 사용 예로 들자면

 NSNumber *memory;

 memory = [NSNumber initWithInteger];

 

 initWithInteger 메소드를 호출하면

 NSNumber는 알아서 메모리 공간을 정수형으로 할당해서 memory에 주소를 넘겨준다.

 

 아예 처음부터 값을 넣어줄수도 있다.

 memory = [NSNumber numberWithInteger : 10];

 

 아예 처음부터 10으로 초기화 해버린 것이다.

 

 NSString

 

 문자열을 다루는 객체이다.

 예를 들어보자

 NSString *string = [NSString stringWithString : @"hello];

 

 위의 내용은 문자열공간을 할당하여 hello를 저장하여 주소를 string에 넘겨주었다.

 다음 내용도 거의 동일하다.

 NSString *string = @"hello";

 

 하지만 NSString 객체는 문자열을 수정할 수가 없다.

 C++에서도

 char *string = "hello";

 string[2] = 'k';

 라고 하면 문자열 내부의 값을 바꾸려고 하면

 [value is Constant. Can't change] 에러메시지가 뜬다.

 값이 상수라서 변경을 할수 없다는 것이다.

 

 NSString은 상수문자열을 저장하는 객체이다.

 수정이 가능한 문자열 객체를 원한다면

 

 NSMutableString 객체를 사용하길 바란다.

 

 정리하면, 문자열에는 수정불가능한 문자열과, 가능한 문자열이 있다는 것이다.

 기억해두자.

 

 NSArray

 

  이것은 배열을 관리해주는 객체이다.

 일반 C의 배열과 다른점은 C에서

 int array[10]; 이라고 했을시에 array에는 int형 값만 넣을수 있다는 것인데

 NSArray는 무엇을 넣든 상관이 없다.

 

 NSNumber처럼 배열을 관리해주는 관련 메소드가 많다

 (상당히 많기 때문에 다른곳에서 레퍼런스를 찾아 읽어보길 바란다.

  그리고 나도 NSArray는 거의 사용해보지 않았다. 아직도 내겐 int array[]가 익숙하다)

 

NSAutoReleasePool

 

 앞장에서 Objective C 첫예제를 기억할 것이다.

 

int main()

{

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

 NSLog(@"hello world");

 [pool drain];

}

 

 pool 변수에 NSAutoreleasePool객체를 할당받아서 초기화하고 주소를 저장하였다.

 대체 pool 객체가 뭘까?

 

 사실 이 pool객체는 메모리 관리를 좀더 쉽게 해주기 위해서 있는 것이다.

 pool객체에는 우리가 alloc 메소드로 만들어내는 '객체들의 참조하는 갯수'들이 저장이 된다.

 

 근데 이게 왜 필요할까?

 한번 예를 들어보겠다.

 

void main()

{

 int *a = new int;

 int *b = a;

 delete a;

}

 이 상황을 그림으로 표현하면

 

 이렇게 될 것이다. 근데 이 상황에서

 delete a;를 해버리면

 

 a가 참조하고 있던 int형객체를 메모리에서 지우게 되는데

 a는 더이상 참조하지 않으니까 별문제 없지만

 b는 존재하지도 않는 int객체를 참조하고 있기 때문에

 문제가 발생하게 된다.

 

 "난 저런 실수 안해"

 물론 변수 달랑 두개가지고 참조하는 걸로 실수할 사람은 별로 없을 것이다. 문제는

 

 한개의 객체를 참조하는 변수가 10개이상이라면..

저 10개중 한놈이라도 delete를 호출하여 메모리를 해제하게 될 시 나머지 변수들은 매우 곤란한 상황에 처하게 된다.

 만약 저 int형객체를 참조하는 횟수를 알고 있다면 참조하고 있는 놈들 중 한놈만 남기고

전부 0으로 초기화 하면 되긴 하지만, 횟수를 알기는 힘들기 때문에 관리가 어렵다.

 

 그래서 Objective C에서는 NSAutoreleasePool이라는 "내가 대신 관리해줄게" 클래스가 있다.

이 클래스는 NSObject클래스로부터 '상속'되었다.

(NSObject에서 상속되었다는 사실은 매우 중요하다. 아래에서 설명하겠다)

 

기억해둘것

 앞장에서 언급안한것 같아 여기서 설명한다

C와 Objective C에서는 메모리 할당 메소드와 해제 메소드 이름이 다르다.

 

C는

 int *a = (int*)malloc(sizeof(int));

 free(a);

 

C++에서는

 int *a = new int;

 delete a;

 

Objective C에서는

 int *a = [[int alloc]init];

 [a dealloc];

 

이다.

 실제로 free = delete = dealloc 다 물리적으로 같은 일을한다.

RAM에 잡아두었던 메모리를 해제하는 것이다.

 하지만 Obective C에서는

 dealloc 대신 release라는 메소드를 더 많이 쓴다.

 

 release역시 dealloc과 비~슷한 일을 한다.

 하지만 차이가 있다.

 

 어떻게 차이가 있을까 보자

 

int main()

{

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

 Swordman *sword = [[Swordman alloc]init];

 Swordman *sword2;

 Swordman *sword3;

 NSLog = (@"Swordman count = %i",[sword retainCount]);

 [sword2 addObject: sword];

 NSLog = (@"Swordman count after addObject = %i",[sword retainCount]);

 [sword2 release];

 NSLog = (@"Swordman count after release = %i", [sword retainCount]);

 [sword release];

 NSLog(@"Dealloc has executed");

 [pool drain];

}

결과

 Swordman count = 1

 Swordman count after addObject = 2

 Swordman count after release = 1

 Dealloc has executed

 

 sword 변수에는 alloc으로 메모리를 할당해서 객체를 생성하였다.

 그리고 메모리에 만들어진 Swordman 객체를 참조하는 것은 sword 하나밖에 없기 때문에

 참조횟수가 1이 나오는 것이다.(retainCount는 참조횟수를 뜻한다)

 

 근데 sword2에 addObject를 통해 sword 주소를  sword2에 복사하였다.

 그래서 다음 NSLog에서 참조횟수가 2가 된 것이다.

 

 그림으로 표현하자면

 

 이렇게 될 것이다. 두 객체변수가 메모리에 잡혀있는 Swordman 객체 하나를 참조하고 있다.

 근데 여기서

 [sword2 release]를 하면

 release 메소드는

 sword2를 0으로 만들고

 참조횟수를 1 감소시킨다.

 

 이 사실은 매우 중요하다.

 dealloc은 메모리를 '정말' 지우는 반면에

 release 참조횟수가 2이상이면 메모리를 지우지 않고, 참조횟수만 1 줄인것이다.

 만약 참조횟수가 1일때 release 메소드가 실행된다면

 

 release 메소드는 자동으로 dealloc을 호출하여 물리적으로 메모리를 해제할 것이다.

 

 이것은 매우 중요한 개념이다. 이해가 안간다면 다시 읽기를 권한다.

 

한가지 더-----------------------------------------------------------

 궁금하지 않은가? 어떻게 release메소드는 참조횟수를 알고있는 걸까?

힌트는 NSAutoreleasePool이 NSObject에서 상속되었다는 것이다.

 

.

.

.

.

.

 눈치챈 사람도 있을 것이다.

 NSObject 내부에 객체들의 참조횟수를 저장하는 공간이 있는것이다.

 NSAutoreleasePool은 NSObject와 상속관계이기 떄문에 그 공간에 있는 참조횟수를

 확인할 수 있다.

 

 그리고 자주봐서알겠지만 Objective C에 사용자 정의 클래스들은 거의

 @interface Swordman: NSObject

 

 NSObject의 상속 클래스이다.

 그림으로 표현하자면

 

 (미안하다.. 못그려서)

 ----------------------------------------------------------------

 

 pool에 의한 참조갯수에 대한 이야기를 하고 있었다.

 하지만 아직도 한가지 의문이 남는다.

 

 [pool drain]

 이건뭘까?

 

 이걸 설명하기 전에 autorelease 라는 메소드에 대해서 배워보자.

 제일 좋은 설명방법은 역시 예를 드는 것이다.

 

int main()

{

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

 Swordman *sword = [[Swordman alloc]init];

 NSLog(@"Swordman count after alloc = %i", [sword retainCount]);

 [sword autorelease];

 [pool drain];

 NSLog(@"Swordman count after drain = %i", [sword retainCount]);

}

결과

 Swordman count after alloc = 1

 Swordman count after drain = 0

 

 

 아까 그 예제인데 뭔가 좀 틀리다.

 [sword autorelease]가 추가되었다

 

 이 말은 sword변수가 참조하는 Swordman객체 메모리를

 pool에서 관리해달라고 요청하는 것이다.

 

 이렇게 되면 [pool drain]을 실행하면

 autorelease로 등록되어 있는 sword는 자동으로 dealloc된다.

 

 

 

 

 마치며

 

 아직도 설명하지 못한 것들이 있는데, 아카이빙, 객체복사 등이 있는데 그것들은 직접 찾아서 이해하길 바란다. 내가 다루고 싶긴해도 아직 나 역시 그부분에 대한 이해가 완벽하지 않기 때문에 괜히 어설프게 설명했다가 읽는사람들이 피해를 볼 수 있기 때문이다.

 (물론 여태껏 내가 설명했던 내용이 완벽하다는 건 아니다)

 

 아무튼 Objective C와 C++의 차이점에 대해선 여기까지 다루겠다.

 

 다음 내용으로는 표준 그래픽 라이브러리인 OpenGL ES 2.0을 다루도록 하겠다.

 

 혹시 틀리거나 이상한 부분이 있으면 덧글로 알려주시면 감사하겠습니다.

'프로그래밍 > Mac' 카테고리의 다른 글

Objective C를 배워보자(1)  (0) 2011.09.09
아이폰 SDK 개발자가 되자 (Part2)  (0) 2011.09.09
아이폰 SDK 개발자가 되자 (Part1)  (0) 2011.09.09
블로그 이미지

TailsPrower

,

iPhone 프로그래밍을 들어가기 전에 배워야 할 기본적인 Objective C에 대해서 알아보자.

 

 Objective C는 Mac에서 쓰는 프로그래밍 언어이다.

 iPhone 프로그래밍을 하기 위해서는 반드시 알아야 하는 언어이다.

 이 내용은 원문 "Programming in Objective C 2.0"을 읽고 작성되었으며 철저히 기본 C와 C++를 익혔던 사람의 입장에서 쓰여졌다.

 그러므로 여기 내용이 이해가 가지 않는다면 C,C++를 먼저 정독하고 보거나, 그냥 서점에 있는 "Programming in Objective C 2.0"책을 사서 배우길 권한다.(하지만 이책 역시 C와 C++를 모르는 사람이 접하기엔 너무 간결하게 설명하고 있다..)

 

 그리고 나도아직 Objective C를 잘 모르는 상태에서 시작하는 것이니 완전한 설명은 기대하지 말자.

 

 이곳에서 언급되는 Objective C 내용들은 C와 다른 부분만 적을 것이므로, 나오지 않는부분은 C와 동일하다고 보면 된다.

 찾기 (Ctrl + F)를 사용하면 정보검색이 빠르다.

 

1.Xcode에서 기본 프로그래밍 환경 조성하기

 

 

Finder를 클릭후 자신의 하드디스크를 클릭하면, developer 폴더가 있다.

Developer -> Application -> Xcode를 실행시킨다.

 

 

요런 화면이 뜨면 Create New Xcode Project를 누른다.

 

 

거기서 왼족 하단에 Application을 클릭. 오른쪽 상단에 Command Line Tool을 선택하고 가운데에 Type를 "Foundation"으로 맞추고 choose를 누른다.

 (만약 저 type에서 C를 한다면 친근한 c문법을 기초로 하는 printf("Hello World");가 보일 것이다. 하지만 우리는 Objective C를 해야 하니 Foundation을 선택하자.)

 

 

 

요런 화면이 뜨는데 참 Visual Studio랑 닮은 것 같다. 왼쪽은 폴더들을 표시하고

오른쪽 상단은 폴더안에 파일들을 표시하고

제일 큰 부분을 차지하는 오른쪽 하단 창은 파일의 내용을 표시한다.

 

안에 이미 Hello World를 기본으로 출력해주는 프로그램이 완성되어 있으므로 위의 "Build and Go"를 클릭하면 실행된 화면을 볼수 있다.

.

.

.

 

 응? 아무것도 안보이는데?... 아.. 생각해보니 콘솔창은 Hello World를 출력하고 바로 사라진 모양이다. 콘솔창을 띄워서 어떻게 출력이 되었는지 보자.

 

 

상단메뉴에 RUN을 클릭해보면 Console이라고 있다. 그걸 눌러보면 막 난잡한 글속에 "Hello World"글귀가 보인다. 제대로 실행된 것이다.

 

 이정도면 Objective C 프로그래밍 연습할 준비가 되었다.

 

2.전처리구문

 

 C에서는

 #include <stdio.h>

 

 이렇게 하였으나

 

 Objective C에서는

 #import <Foundation/Foundation.h>

 

 이렇게 한다. Foundation.h는 stdio.h와 비슷한 입출력기능 같은 내용이 정의되어있는 헤더이다.

 

3. 확장자명

 

 C는 ***.c  ,   C++은 ***.cpp 확장자를 가지나

 Objective C는 ***.m   Objective C++는 ***.mm을 가진다

 

4. 출력구문

 

 C는 printf 함수를 사용하나 Objective C는 NSLog를 사용한다.

 

 예) NSLog(@"Hello World %i %i", a , b);

 

   printf에서는 정수형 인수를 %d로 표현하지만, 여기선 %i로 표현한다. 문자열 앞에 @는 NSLog에서 문자열을 출력하는데 쓰는 문법이므로 너무 크게 신경쓰진 말자.

 

5. 클래스 선언

 

C++에서

class Golf : NSObject

{

   int a;

   int b;

   void printMember(void)

}

 

void Golf::printMember(void)

{

 printf("a is %d, b is %d", a , b);

}

 

로 NSObject에서 상속된 Golf 클래스를 생성했다면

 

Objective C에서는

@interface Golf : NSObject

{

  int a;

  int b;

}

-(void) printMember;

 @end

 

@implementation Golf

 

-(void) printMember

{

 NSLog(@"a is %i, b is %i", a, b);

}

@end

 

로 표현한다.

 

 차이점은 @interface로 시작해서 @end로 끝난다는 점이다. interface안에서는 선언만 하고 메소드의 구현은 implementation에서 이루어진다.

 메소드 선언 부분의 '-(void) printMember'에서 맨앞에 -는

 

-(void) printMember 로 만들시에는

 클래스 인스턴스가 만들어졌을때만 사용이 가능한 메소드이며

 

+(void) printMember 로 만들시에는

 인스턴스가 없어도 메소드를 사용할 수 있다.

 

예) -(void) printMember 메소드 호출

 Golf *one = [[Golf alloc] init];

 [one printMember];

 

 첫째줄 :one이라는 포인터 변수를 만들고 동적할당으로 주소를 받는다.

 둘째줄 : one을 통해 메소드 printMember를 호출한다.

 

예) +(void) printMember 메소드 호출

 [Golf printMember];

 

 그냥 클래스명과 메소드 이름만 써서 바로 호출할 수 있다.

 (하지만 이것은 심각한 에러를 초래할 수 도있다. 왜냐하면 printMember 메소드는 인스턴스 내의 변수의 값을 출력하기로 되어 있기 때문에 존재하지도 않는 것을 출력하려고 하기 때문이다.)

 

 여기서 처음보는 것이 있는데

 [Golf alloc]

 일 것이다.

 

 Golf는 클래스 이름이고 alloc은 메소드 이름이다. alloc 메소드는 C에서의 malloc함수와 비슷한 역할을 한다. 근데 Golf내에는 alloc이라는 메소드가 없는데 메소드를 호출이 가능한 것은 NSObject 클래스에서 상속받았기 때문이다. Golf클래스는 NSObject에게서 상속받았기 때문에 alloc 메소드로 동적할당 받을 수 있으며, init 메소드로 초기화를 쉽게 할 수 있다.

 

 NSObject를 기억해두자.

 

 몇가지 예문을 통해 C와 다른점을 보자.

 

예문1. 분수 출력 프로그램

------------------------------------------------------------------

 

//분수를 다루는 프로그램 - 클래스 버전

#import <Foundation/Foundation.h>

//-- @interface부분---

@interface Fraction: NSObject

{

  int numerator;

  int denominator;

}

-(void) print;

-(void) setNumerator: (int) n;

-(void) setDenominator: (int) d;

@end

 

//---implementation 부분--

@implementation Fraction

-(void) print

{

 NSLog(@"%i/%i", numerator, denominator);

}

-(void) setNumerator: (int) n

{

  numerator = n;

}

-(void) setDenominator: (int) d

{

 denominator = d;

}

@end

 

//---program 부분--

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

{

  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  Fraction *myFraction;

//Fraction 인스턴스 생성

  myFraction = [Fraction alloc];

  myFraction = [myFraction init];

//분수를 1/3로 설정한다

  [myFraction setNumerator: 1];

  [myFraction setDenominator: 3];

//print 메서드를 분수로 표시한다.

  NSLog(@"The value of myFraction is:");

  [myFraction print];

  [myFraction release];

 

  [pool drain];

  return 0;

}

 

-----------------------------------------------------------

 

결과는

 The value of myFraction is:

 1/3

 

 또 처음보는게 나왔다. setNumerator setDenominator 메소드가 인수를 받는다.

setNumerator 메소드는 C문법에서의

 

(void) setNumerator(int n);

{

  numerator = n;

와 동일하다.

 2개 이상의 인수를 받는법은 나도 지금은 모르니 알면 써놓겠다.

 

 

예문2. 연습

--------------------------------------------------

#import <Foundation/Foundation.h>

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

{

  NSAutoreleasePool * pool = [[NSAutorelease alloc] init];

 

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

{

 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

 

 int integerVar = 100;

 float floatingVar = 331.79;

 double doubleVar = 8.44e+11;

 char charVar = 'W';

 

 NSLog (@"integerVar =  %i", integerVar);

 NSLog (@"floatingVar = %f", floatingVar);

 NSLog (@"doubleVar = %e", doubleVar);

 NSLog (@"doubleVar = %g", doubleVar);

 NSLog (@"charVar = %c", charVar);

 

 [pool drain];

 return 0;

 

}

 

----------------------------------------------------------------

 

실행결과

 

 integerVar = 100

 floatingVar = 331.79

 doubleVar = 8.440000e+11

 doubleVar = 8.44e+11

 charVar = 'W'

 

 말이 필요없다. Objective C에서도 C처럼 비슷한 변수 선언을 한다. 보고 깨닫도록 하자.

 

6. 클래스 & 메소드 관리 방법

 

 아는 사람들은 잘 알겠지만 왠만하면 선언문과 구현부분은 헤더와 c파일에 나누어 놓는게 좋다는 것을 알 것이다. Objective C에서도

 

***.h

에 다 선언해놓고,

 

구현부분은

***.m

부분에 해놓는게 좋다.

 

***.h 내용

 

#import <Foundation/Foundation.h>

@interface Gogo: NSObject

{

 int a;

}

-(void) print;

@end

 

***.m 내용

 

#import "***.h"

@implementation Gogo

-(void) print

{

 NSLog(@"Hi there");

}

@end

 

 

이런식으로 관리하길 바란다. (***는 임의의 파일명이다)

 

7. 프로퍼티(property)

 C++에서는

 

class KT

{

public:

 int a;

}

 

void main()

{

 KT *instance = new kT;

 KT->a = 3;

}

 

이런식으로 인스턴스의 변수의 값을 직접적으로 접근이 가능하다.(멤버가 public(공용)이라는 전제에서만..)

 하지만 Objective C에서는

 

@interface KT:NSObject

{

 int a;

}

@end

 

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

{

 KT *instance = [[KT alloc] init];

 instance->a = 3;  //이런 문법은 불가.

}

 

 instance->a 같이 접근하는 문법은 존재하지가 않는다. 그렇기에 따로 멤버의 값을 조정하는 setMember 메소드 같은걸 만들어서 조절을 할 수밖에 없는데...

 

 프로퍼티(property)라는 문법을 사용하면 쉽게 멤버 값을 바꿀 수 있다. 우선은 클래스 선언부분에

 

@interface KT:NSObject

{

 int a;

}

@property int a; //이부분 추가

@end

 

 위와 같이 추가하고 구현 부분에

 

@implementation KT

 

@synthesize a; //이부분 추가

 

@end

 

 저 부분을 추가한다.

저렇게 해놓으면 메인에서

 

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

{

 KT *instance = [[KT alloc] init];

 [instance a = 3];  // 이런 방법도 가능하고

 instance.a = 3; //이런 방법도 가능하다.

}

 

 저렇게 사용이 가능하게 된다.

 어휴.. 평소에 잘 쓰던 문법도 Objective에서는 저렇게 설정해줘야만 되나보다.

 

 오늘은 여기까지...

'프로그래밍 > Mac' 카테고리의 다른 글

Objective C를 배워보자(2)  (1) 2011.09.09
아이폰 SDK 개발자가 되자 (Part2)  (0) 2011.09.09
아이폰 SDK 개발자가 되자 (Part1)  (0) 2011.09.09
블로그 이미지

TailsPrower

,

일단 혹시 매킨토시에 대해 잘 모르는 사람을 위해서

http://x86osx.com/bbs/view.php?id=osxtips&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=2050

이러한 가이드를 써놓은 사이트도 있다. 꼭 읽어보자.

 

그리고 다 읽어보았다면 아래 사이트를 참조.

VMware로 스노우 레오파드 리테일을 까는법을 설명하고 있다.

http://x86osx.com/bbs/view.php?id=osxtips&page=1&sn1=&divpage=1&sn=on&ss=off&sc=off&keyword=조준기&select_arrange=headnum&desc=asc&no=1941

 

이 사이트에서 하라는 대로 하면 되고,

 

따로 필요한 것은 스노우 레오파드 10.6 리테일 인데,

 

내가 첨부한 토렌트 파일로 받으면 된다.

 

(토렌트는 p2p같은 것이다. 받으려면 일단 토렌트부터 설치해야 한다)

 

그리고 아이폰4 SDK를 받아서 설치하면 된다.

 

 

 

(정작 10.6.4 OS 설치하는데에 2주나 걸렸다.... 반갑다 설범 바탕화면!)

 

왠만하면 여기저기 맥에 대한 정보들을 일주일간 수집해보는 것을 추천한다.

(맥의 기반이 UNIX라던지, UNIX는 윈도우랑 다른점이라던지, 스노우 레오파드가 왜 일반 PC에서는 작동안되는지 등)

 

많이 알수록 차후에 여러가지를 하는데에 많이 도움이 될 것이라 생각한다.

 

나역시 이놈에 설범깔려고 2주동안 검색검색, 설치,지우기 설치 지우면서 여러가지를 배운 것 같다.

 

몇가지 모를 수 있는 용어정리를 하자면

 

VMware Workstation7 - 가상머신이라는 것으로 컴퓨터 내부에서 또다른 컴퓨터를 가상으로 만드는것.. 이것을 통해서 스노우 레오파드를 가상컴퓨터에 설치할 수 있다.

 

Snow Leopard 10.6.4 - iPhone안에 만드는 애플리케이션들은 맥OS프로그래밍의 기반인 Objective C 기반으로 되어 있다. 그렇기에 아이폰 프로그래밍 역시 맥에서 밖에 할 수 없는데, 맥에 깔려있는 OS가 바로 스노우 레오파드 (설범이라고도 함)이다. 그리고 이번에 나온 iPhone4의 SDK는 버전 10.6.4이상에서만 작동한다.

 

darwin - 모르겠다. VMware에서 Mac OS가 제대로 작동하도록 도와주는 프로그램인듯하다.

 

torrent - 위에서 말했지만, 당나귀,프루나 같은 p2p프로그램이다. 단지 해당 토렌트 파일을 가지고 있어야만 파일을 받을수가 있도록 되어 있다.

'프로그래밍 > Mac' 카테고리의 다른 글

Objective C를 배워보자(2)  (1) 2011.09.09
Objective C를 배워보자(1)  (0) 2011.09.09
아이폰 SDK 개발자가 되자 (Part1)  (0) 2011.09.09
블로그 이미지

TailsPrower

,

iPhone 프로그래밍을 하려면.......

 

iPhone 프로그래밍의 맞는 환경에서 작업해야 한다.

 

iPhone이 Apple에서 만든 물건이라 그런지 여기 안에 있는 운영체제 시스템인 iOs는 Mac OS랑 흡사하다.

 
Mac OS에서는 프로그래밍을 하려면 Object C라는 언어를 알아야 한다.

 
하지만 진짜 문제는 이 프로그래밍을 하려면 윈도우가 아니라 MacOS에서 작업해야 한다는 것.

 

그렇다면 다음과 같은 방법들을 생각해볼수있다.

 

1.매킨토시 컴퓨터 중고를 하나 산다. (요새 아이폰 때문에 중고 매킨토시가 많이 팔려 구하긴 쉽지않을듯)

2.멀티부팅으로 윈도우 옆에 MacOSX 깐다. (..이건 매우 방법이 어렵다고 알려져 있는..)

3.VMware(가상 머신)를 이용하여 Mac OS를 까는 것 (안정적인 방법)

 

현실적으로 내겐 1,2번은 힘들어 보인다.

 

그래서 선택한 것이 3번 VMware!!

 

VMware는 컴퓨터 안에 또다른 컴퓨터를 만들어 컴퓨터가 꼭 두대인것처럼 사용하는 프로그램이다.

(자세한 설명은 생략한다)

 

 하지만 본인의 CPU가 Virtual Technology(가상화 기술)이 적용되는지 확인할 필요가 있는데

 

SecurAble

이것을 다운받아서 실행시켜보면

 

위와같이 64비트를 지원하고 가상기술을 지원해야만 된다

 

 

위와 같이 뜰때는 안된다는 것이다.

32비트 하드웨어나 가상기술이 지원안될때도 된다고 알고있으나

그방법은 여기서 다루진 않겠다.

 

일단 64비트 지원에 가상기술이 된다면 아래의 VMware를 네이버에서 때려서 받으면 된다.

vmware workstation v7.0.1 build 227600

 

그리고 가상머신에서 돌릴 Mac OS가 필요한데 난

Snow Leopard 10.6 버전을 받아서 사용하였다.

 

다음장에서 좀더 자세히 다루겠다.

 

'프로그래밍 > Mac' 카테고리의 다른 글

Objective C를 배워보자(2)  (1) 2011.09.09
Objective C를 배워보자(1)  (0) 2011.09.09
아이폰 SDK 개발자가 되자 (Part2)  (0) 2011.09.09
블로그 이미지

TailsPrower

,