달력

10

« 2024/10 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2010. 5. 11. 20:54

[4일차]레퍼런스 카운트 Objective-C2010. 5. 11. 20:54


레퍼런스 카운트

1. 인스턴스의 참조 횟수
2. Objective-C 에서는 인스턴스 관리를 위해 레퍼런스 카운트(레퍼런스 참조횟수)를 저장하고 있는데
   alloc을 하는 순간 메모리를 할당하고 카운트 값을 1로 초기화 합니다.
3. retain 메서드는 이 카운트 값을 1 증가 시키고 자기 자신의 id를 리턴합니다.
4. release 메서드는 이 카운트 값을 1 감소 시킵니다.
5. dealloc은 이 참조 카운트 값을 무시하고 무조건 메모리 공간을 해제합니다.
6. objective-C 는 참조 카운트 값이 0인 인스턴스를 해제합니다.
7. retainCount 메서드를 호출하면 그 인스턴스의 참조횟수를 정수로 리턴합니다.
------------------------------------------------------------------------
#import <foundation/foundation.h>

int main()
{
   id obj = [[NSObject alloc] init];
   NSLog (@"Init : %d\n",[obj retainCount]);
   [obj retain];  
   NSLog (@"retain : %d\n",[obj retainCount]);
   [obj retain];  
   NSLog (@"retain : %d\n",[obj retainCount]);
   [obj release];  
   NSLog (@"release : %d\n",[obj retainCount]);      
   [obj release];  
   NSLog (@"release : %d\n",[obj retainCount]);         
   [obj release];  
   NSLog (@"release : %d\n",[obj retainCount]);            
   // retainCount : 0 이므로 가리키고 있는 객체가 없는 상태임. 따라서 런타임 오류가 발생
   system("pause");
   return 0;
}
------------------------------------------------------------------------

dealloc
dealloc을 호출하는 것은 에러가 아님
retainCount에 상관없이 해제를 하므로 약간 위험할 수 있음
------------------------------------------------------------------------
#import <foundation/foundation.h>
int main()
{
   id obj = [[NSObject alloc] init];
   NSLog (@"Init : %d\n",[obj retainCount]);
   [obj retain];  
   NSLog (@"retain : %d\n",[obj retainCount]);
   [obj dealloc];  
   NSLog (@"dealloc : %d\n",[obj retainCount]);
   // retainCount 런타임 오류가 발생하면 메모리 할당이 되어 있지 않다는것을 확인 할 수 있음
   system("pause");
   return 0;
}
------------------------------------------------------------------------
그러나 무턱대고 dealloc를 호출하면 위험함..
가령 위의 구문을 복사할 경우 문제가 발생
------------------------------------------------------------------------
#import <foundation/foundation.h>
int main()
{
   id obj = [[NSObject alloc] init];
   NSLog (@"Init : %d\n",[obj retainCount]);
   [obj retain];  
   NSLog (@"retain : %d\n",[obj retainCount]);
//   id obj1 = obj;  
   id obj1 = [obj retain];   // <= retainCount 증가를 통해 잘못된 메모리 해제를 방어
   if ([obj retainCount]==1)
   {
      [obj dealloc];
   }
// [obj dealloc];  
   NSLog (@"dealloc : %d\n",[obj1 retainCount]);
   // 참조복사를 한 경우 참조가 삭제되어 문제가 발생
   // c#의 경우 참조가 걸려 있으면 dealloc을 할 수 없음.
   // release 도 동일한 문제가 발생할 수 있으므로 retain 을 확인해야 함.
   // retain은복사를 하거나 매개변수로 사용되었다는것을 알려주기위해 만들어짐.  
   // 인스턴스가 매개변수로 사용될때 고민해야 함.
   // 함수생성시 매개변수에 포인터를 쓰는것은 위험한 발상이다.(중간에 하나만 끊겨도 많은 문제가 야기된다)
   // 멤버가 public 라면 init 생성시 매개변수로
   // @interface Test
   // -(id) init : (Test*) x   
   // { self = x }
   // [[Test alloc] init:x];

   system("pause");
   return 0;
}

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

안전하게 복사하는 방법
   // int a=10;
   // int *p = (int*) malloc(4);
   // *p = a;
   // free(p);


dealloc은 재정의 가능
1. 반드시 super dealloc을 호출해야 하고 release를 이용해서 사용하는것이 바람직하고 일반적으로 정리작업에 사용
------------------------------------------------------------------------
#import <foundation/foundation.h>
@interface Test : NSObject
{
   @public
   int a;
}
-(id)init :(Test*)obj;
@end

@implementation Test
-(id)init:(Test*)obj
{
   self = [super init];
   if(self !=nil)
   {
      self->a = obj->a;
   }          
   return self;
}
@end

Test obj=[Test alloc];
Test obj1=[[Test alloc]init:obj];
------------------------------------------------------------------------
NSString 상수
1. @"문자열"
2. 프로그램 종료시까지 해제되지 않는 인스턴스임.
3. retain, release 무시
4. retainCount 는 양의정수 최대값에서 불변입니다.

const
1. 변수를 상수화시켜주는 예약어
2. C 에서와 거의 동일하게 사용되지만 멤버로 선언하지 않는다는점이 다름.
3. # define과도 유사하지만 #define은 컴파일시 이미 변경이 된다는 점이 다름.
4. 클래스 구현부에서 선언하자마자 초기화하면 전역변수처럼 사용됨.
    * 일반 value형 변수에 사용되면 값을 변경할 수 없음. => * 안들어가는 id를 제외한 자료형
    * 포인터변수에 사용되면 주소(id)는 변경할 수 있지만 가리키는 데이터는 변경할 수 없다.
5. 인스턴스(멤버) 변수에 const를 지정하면 0으로 사용 - 초기화를 수행하고 난후 변경할 수 없음
------------------------------------------------------------------------
#import <foundation/foundation.h>
@interface Test : NSObject
{
   int a;
   const int b;
}
-(int)a;
-(int)b;
-(void)setA:(int)n;
-(void)setB:(int)n;
@end

@implementation Test
-(int)a {return a;}
-(void)setA:(int)n
{
   a=n;                
}
-(int)b {return b;}

-(void)setB:(int)n
{
//   b=n; // read-only member err
}
@end


int main()
{
   Test * obj= [[Test alloc]init]; // id를 리턴
   
   NSLog(@"%d",[obj a]);
   [obj setA:20];
   NSLog(@"%d",[obj b]);
   [obj setB:20];
   NSLog(@"%d",[obj b]);  
   system("pause");
   return 0;
//   int a=10;
//   const int c=10;
//   NSLog(@"%d",a);
//   NSLog(@"%d",c);
//   a=11;
//   c=11; // readonly , error
//   return 0 ;
}

자료명이름 * 변수명; <-포인터변수 정의

alloc
메모리를 할당하고 모든 멤버변수를 0로 초기화
initialize :
init : 재정의 가능




:
Posted by 에너지발전소
2010. 5. 10. 22:01

[3일차]nil 포인터(3-2) Objective-C2010. 5. 10. 22:01

1. 참조되는 대상이 없는 포인터
2. 메모리 할당에 실패했거나 메모리 할당을 아직 하지 않은 경우의 포인터
3. 0 이라고 하는 경우도 있음
4. 다른 언어의 null과 유사
   다른 점은 다른 언어는 null이 멤버를 참조하면 컴파일시 에러지만 objective-C는 실행 시 에러 (예외로 처리)
   웬만한 참조형 변수를 사용할때에는
   if ( obj !=nil) 
   {
      [obj Disp];
   } else {
      obj = [Test alloc];
      [obj Disp];
   }
 
헤더 파일 import 대신 사용할 수 있는 구문

@class 클래스명;


인스턴스의 멤버 변수접근
1. objective-C 에서는 기본적으로 인스턴스의 멤버변수에 접근할 수가 없습니다. - 정보은닉 (infomation Hiding)
2. 예외적으로 클래석 구현부내에서 Self를 이용한 접근은 허용하지만 큰 의미가 없으며 클래스의 인스턴스가 메서드의
    매개변수인 경우에도 가능 (-> 연산자 이용)

@interface Test : NSObject
{
    int a ;
}
-(void)Disp;
@end
Test * obj = [Test alloc];
NSLog (@"%d\n",obj->a); (X)
[obj Disp]; (O)
 
------------------------------------------------------------
#import <Foundation/Foundation.h>
@interface Test : NSObject
{@public
   int n;
}
-(id)init:(int)a;
------------------------
** public를 사용하지 않을 경우
-(int)n;   --> get method
-(void)setN:(int)a;  --> set method

------------------------
@end

@implementation Test
-(id)init:(int)a;
{
   n = a;
}
------------------------
** public를 사용하지 않을 경우
-(int)n {return n;}
-(void)setN:(int)a
{
   n = a;                
}
------------------------
@end

@interface TempTest : NSObject
{
   int value;
}
-(id)init:(int)a;
-(void)disp:(Test*)obj;
@end

@implementation TempTest
-(id)init:(int)a;
{
   value = a;
}
-(void)disp:(Test*)obj;
{
   NSLog(@"%d\n",value);                     
   NSLog(@"%d\n",obj->n);                     
}
@end

int main(void)
{
  Test *Ins = [[Test alloc]init:10];
  TempTest *var = [[TempTest alloc]init:20];
  [var disp :Ins];
  system("pause");
  return 0;
}
------------------------------------------------------------

접근 지정자

@private : 클래스 내에서만 접근가능
@protected : 클래스 내부에서 접근가능하고 상속한 경우 접근가능 (생략하면 Protected)
@public : 클래스와 인스턴스 모두 접근 가능 

클래스는 무조건 public (내포 클래스 지정불가능)
클래스 안에 클래스 지정하는것이 불가능.

Property(속성)

지역 메서드
1. 선언부(Interface)에는 없고 구현부(implementation)에만 있는 메서드


Static(클래스)
1. 클래스가 사용할 수 있는 또는 인스턴스들이 공유할  수 있는 멤버
1) Static 메서드 (클래스 메서드)
    가) 인스턴스 생성없이 사용할 수 있는 메서드
    나) - 대신에 +를 붙이면 Static 메서드
    다) 인스턴스가 호출 할 수 없다.
    라) 인스턴스 변수 사용 불가


    마) 굉장히 자주사용하거나 Static 변수 선언시에 사용.
    바) 코드,전역 영역    /     스텍      / Heap


2. Static 변수
    가) 동일한 클래스 타입으로 만들어진 인스턴스들이 공유할 목적으로 사용하는 변수
    나) 인스턴스가 호출해야 합니다. (Self 같은 애들이 사용)
    다) 일련번호를 만들때 적절히 사용

    라) 선언하고자할때 static를 기재하면 되고 구현부에서 생성하자마자 초기화해서 사용
    마)
------------------------------------------------------------
#import <Foundation/Foundation.h>
@interface Test : NSObject
-(void)Disp;   -> 인스턴스 메서드
+(void)Print;   -> 클래스 메서드
@end

@implementation Test
-(void)Disp
{
   NSLog(@"Instance 멤버");
}
+(void)Print
{
   NSLog(@"Class 멤버");
}
@end

int main(void)
{
  [Test Print];
  Test *obj = [[Test alloc] init];
  [Test Print];
  [obj Disp];
  system("pause");
  return 0;   
}
------------------------------------------------------------
// 일련번호 만들기
#import <Foundation/Foundation.h>
@interface Test : NSObject
{
  int bunho;
}
- (id) init;
- (void) Disp;
@end


@implementation Test : NSObject
static int n = 1; // test 타입은 전부 공유
-(id) init
{
   self -> bunho = n++; return self;
}
-(void)Disp
{
   NSLog(@"%d\n",bunho);
}
@end


int main(void)
{
  Test *obj1 = [[Test alloc] init];
  Test *obj2 = [[Test alloc] init];
  [obj1 Disp]; //1
  [obj2 Disp]; //2
  system("pause");
  return 0;   
}

:
Posted by 에너지발전소
2010. 5. 10. 19:48

[3일차]Dynamic Binding(3-1) Objective-C2010. 5. 10. 19:48


음.. 2일차 정리되지 않은 관계로 3일차 먼저 정리하고.. 2일차는 다음에 다시 정리하도록 하겠습니다.

Dynamic Binding

1. Objective-C 에서는 모든 참조형 변수는 Dynamic Binding (실행시 타입을 결정)을 수행합니다.
2. 컴파일시에는 어떠한 타입체크도 수행하지 않습니다.
3. 단, 상위클래서 타입의 변수에 하위타입의 클래스로 메모리를 할당하는 경우 메모리 할당도 가능하고
   하위 클래스 타입의 메서드도 호출가능하지만 하위클래스 타입의 메서드를 호출하면 Warning이 발생한다.
   이때는 가급적 형변환을 해주는것이 좋다.

  상위 클래스의 변수는 하위 클래스타입의 변수 대입가능
 
 
Test *obj = [Test alloc];
  SubTest *obj = [SubTest alloc];
  Test *obj = [SubTest alloc]; ==> Warning 발생 : 형변환을 하면 Warning가 발생하지 않음
                                                 [(Subtest*)obj b] ==> (변경하고자하는자료형)데이터
  SubTest *obj = [Test alloc]; (X) ==> 일반적으로는 불가능하나 Objective-C는 가능

----------------------------------------------------
#import <Foundation/Foundation.h>
@interface Test : NSObject
-(void)Disp;
@end

@implementation Test
-(void)Disp;
{
  NSLog(@"상위 클래스의 메서드입니다"); }
@end

@interface SubTest : Test
-(void)Print;
@end

@implementation SubTest
-(void)Print;
{
  NSLog(@"하위 클래스의 메서드입니다");
}
@end
 
int main(void)
{
  Test * obj;
  obj = [[SubTest alloc] init];
  [obj Disp];
  [(SubTest*)obj Print];  => (SubTest*) 는 생략가능
  system("pause");
  return 0;
}
----------------------------------------------------
  

 

:
Posted by 에너지발전소