본문 바로가기
모바일개발(Mobile Dev)/IOS개발(ObjectC)

[Obj-C] 접근자 @property, @synthesize, @dynamic / retain, copy, assign, atomic, nonatomic

by 테크한스 2015. 1. 29.
반응형

[Obj-C] 접근자 @property, @synthesize, @dynamic / retain, copy, assign, atomic, nonatomic

참고::

http://maclove.pe.kr/28

http://blog.outsider.ne.kr/604

http://lambert.tistory.com/560



@property

 - 객체의 필드에 데이터를 설정하거나 설정된 내용을 참조하기 위해 사용한다.

 - @property 키워드는 프로퍼티를 선언한다. (getter, setter 메소드는 @synthesize 키워드로 자동 구현한다.)

1
@property (readwrite, assign) BOOL enable;




@synthesize

 - 개발자가 프로퍼티에 대한 getter, setter 메소드를 직접 작성하는 대신 @synthesize 키워드를 사용하면 해당 프로퍼티에 대한 접근자를 생성하도록 컴파일러에게 지시한다.

 - 외부에서 접근하는 프로퍼티 이름과 내부의 변수 이름은 항상 일치시킬 필요는 없다. 내부에서 (비용 절감을 위해)직접 접근하는 변수와 외부에서 간접적으로 접근하는 프로퍼티명을 아래와 같이 언더바(_)로 구분시킬 수 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 헤더
@interface AccessorTest2 : NSObject
{
    BOOL _enable;
}
 
@property (readwrite,assign) BOOL enable;
 
@end
 
 
// 구현
@implementation AccessorTest2
 
// 프로퍼티가 전역변수를 사용할 것이라는 것을 정의.
@synthesize enable = _enable;
 
@end

 - 인스턴스 변수(전역변수)를 선언하지 않고 프로퍼티만 선언하였다면 컴파일러는 자동으로 프로퍼티명 앞에 "_(언더바)"를 붙여 인스턴스 변수를 생성하고 @synthesize를 통해 연결을 한다. (프로퍼티명이 value이면 _value이라는 인스턴스 변수를 생성)

 Xcode 4.4 이후로 @synthesize를 직접 작성하지 않아도 컴파일러가 알아서 @synthesize를 추가하게끔 업데이트 되었다. -_-)b

이렇게 _value라는 전역변수가 없지만 value라는 프로퍼티를 선언하면


내부적으로 _value라는 인스턴스 변수를 자동으로 생성하게 된다.



@dynamic

 - @synthesize 대신 사용할 수 있으며 getter, setter 메소드가 클래스 자신에 의해서 구현되지 않고 (슈퍼클래스 같은) 다른 어딘가에 구현되어 있다고 컴파일러에게 알려주어 컴파일시 warning을 받지 않도록 한다.

Super class :

1
2
3
@property (nonatomic, retain) NSButton *someButton;
  
@synthesize someButton;

Sub class:

1
2
3
@property (nonatomic, retain) IBOutlet NSButton *someButton;
  
@dynamic someButton;

위와 같이 작성함으로써 someButton에 대한 구현 책임은 델리게이트 되었음을 의미한다. 혹은 Core Data의 NSManagedObject 클래스처럼 접근자 메소드들이 컴파일 타임이 아닌 런타임시 제공되는 경우에도 컴파일 오류가 나지 않도록 하기 위해서 @dynamic 키워드를 사용할 수 있다.




프로퍼티 선언

1. getter와 setter 메소드를 아래와 같이 임의로 지정해줄 수 있다. 컴파일러는 @synthesize 로 선언한 프로퍼티의 접근자들(getter/setter) 중에서 직접 구현되지 않은 것들을 직접 생성하는데, 이 때 getter와 setter 이름을 아래와 같이 지정해 놓으면 해당 이름을 갖는 접근자를 생성한다.

1
@property (getter = isEnable, setter = setEnable) BOOL enable;

2. 아래 코드는 name 프로퍼티를 오직 읽기만 가능하도록 설정한다. 즉, setter 메소드를 생성하지 않는다. 그래소 만약 self.name = @"test"; 와 같이 하면 컴파일 에러를 발생시킨다. readonly를 설정하지 않으면 default로 readwrite가 설정된다.

1
@property (readonly) NSString *name;

3. 아래 코드에서 nonatomic은 다중 쓰레드에 대해서 고려할지를 선택하기 위한 것이다. 만약 다중 쓰레드 환경에서 여러 쓰레드가 경쟁적으로 접근하는 프로퍼티가 있다면 atomic으로 설정해야 한다. 하지만 그외의 대부분은 nonatomic으로 한다.

1
2
3
@property (nonatomic, retain) UIImage* img;
@property (nonatomic, copy)   NSString* name;
@property (nonatomic, assign) BOOL enable;

나머지 키워드인 retain, assign, copy 이 3가지 속성은 각각 setter의 동작을 결정한다. 아래를 참고하자



retain

1
@property (nonatomic, retain) UIImage* img;

위 코드는 retain으로 설정되어 있다. @synthesize 키워드를 사용하면 컴파일러는 아래와 같은 코드를 만들어 낸다.

1
2
3
4
5
6
-(void) setImg:(UIImage*) newImg {
    if (img != newImg ) {
        [img release];
        img = [newImg retain];
    }
}

즉, 기존 변수에 저장된 객체와 매개변수로 받은 객체가 다르면 기존 객체를 release하고 새로 받은 객체를 설정하고 retain한다.



copy

1
@property (nonatomic, copy) NSString* name;

위 코드는 copy 속성을 이용한다. 컴파일러가 만들어 내는 코드는 아래와 같다.

1
2
3
4
5
6
-(void) setName:(NSString*) newName {
    if (name != newName ) {
        [name release];
        name = [newName copy];
    }
}

copy 메소드는 기본적으로 retain을 한 번 호출하기 때문에 setter 내에서 retain을 추가로 호출하지는 않는다. copy는 값을 복사해서 새로운 객체를 만들기 때문에 인자로 전달되는 객체가 자주 변경될 소지가 있는 경우 적합하다. (copy하는 대상은 NSCopying 프로토콜을 반드시 구현하여야 한다.)



assign

1
@property (nonatomic, assign) BOOL enable;

assign은 그냥 값을 대입시킨다.

1
2
3
-(void) setEnable:(BOOL) en {
    enable = en;
}

객체를 assign으로 설정하는 경우는 외부에서 참조 카운트를 감소시켜 객체가 해제될 위험이 있기 때문에 주의해서 사용해야 한다. 그렇기때문에 assign은 객체가 아닌 BOOL, int 등의 primitive type에 대해 적합하다.



반응형

'모바일개발(Mobile Dev) > IOS개발(ObjectC)' 카테고리의 다른 글

SLIDING MENU DRAWER WITH CUSTOM SEGUES  (0) 2015.03.06
slide menu github  (0) 2015.02.16
activity tracking. what u need to know  (0) 2015.01.28
http://jsonlint.com/  (0) 2015.01.25
xcode delete  (0) 2015.01.25