본문 바로가기
프로그래밍 놀이터/iOS

[Effective Objective-C] #26 카테고리에는 프로퍼티를 사용하지 말라.

by 돼지왕 왕돼지 2017. 9. 10.
반응형

 [Effective Objective-C] #26 카테고리에는 프로퍼티를 사용하지 말라.


출처 : Effective Objective-C

@dynamic, autosynthesis, category property, OBJC_ASSOCIATION_RETATIN_NONATOMIC, objc_getAssociatedObject, objc_setAssociatedObject, synthesize, [Effective Objective-C] #26 카테고리에는 프로퍼티를 사용하지 말라., 구현, 메모리 관리, 메인 인터페이스, 불가능, 연관객체, 인스턴스 변수, 읽기 전용 프로퍼티, 자동 합성, 접근자 메서드, 카테고리 프로퍼티, 클래스 확장 카테고리, 합성


-

기술적으로 카테고리에 프로퍼티를 선언하는 것이 가능할지라도 되도록이면 하지 말아야 한다.

그 이유는 클래스 확장 카테고리를 제외하고는 카테고리가 클래스에 인스턴스 변수를 추가하는 것이 불가능하기 때문이다.

그렇기 때문에 카테고리가 프로퍼티에 해당하는 인스턴스 변수를 합성(synthesize) 할 수도 없다.



-

카테고리에 있는 인스턴스 변수는 합성될 수 없기 때문에 프로퍼티를 위한 접근자 메서드를 카테고리에 구현해야 하고,

그렇게 하지 않으면 접근자 메서드를 @dynamic 으로 선언해야 한다.

@dynamic 으로 메서드를 선언하는 것의 의미는 이 메서드를 실행 시간에는 사용할 수 있지만 컴파일러는 구현을 볼 수 없다는 것이다.

이는 메시징 전달 메커니즘을 사용하여 실행 시간에 메서드를 가로채어 구현을 제공하는 방법으로 가능하다.



-

카테고리가 인스턴스 변수를 합성할 수 없는 문제를 해결하기 위해 연관 객체를 사용할 수 있다.

static const char *kFriendsPropertyKey = “kFriendsPropertyKey”;


@implementation EOCPerson (FriendShip)


- (NSArray*)freinds{

     return objc_getAssociatedObject(self, kFriendsPropertyKey);

}


- (void)setFriends:(NSArray*)friends{

     objc_setAssociatedObject(self, kFriendsPropertyKey, friends, OBJC_ASSOCIATION_RETATIN_NONATOMIC);

}


@end


위 코드는 동작은 하지만 이상적인 해결책은 아니다.

이것은 꽤 많은 보일러 플레이트 코드가 필요하고 메모리 관리에서 에러를 일으킬 확률이 높다.

이렇게 구현한 프로퍼티는 잊어버리기 쉽기 때문이다.


위의 방법은 비록 나쁘지 않은 해결 방법이지만 추천되는 방법은 아니다.



-

카테고리가 아닌 메인 인터페이스 파일에 프로퍼티를 정의하는 것이 가장 깔끔하다.




-

올바른 해결책은 모든 프로퍼티 정의를 메인 인터페이스 파일에서 선언하는 것이다.

클래스에서 캡슐화하려는 모든 데이터는 메인 인터페이스에 정의되어야 한다.

여기가 인스턴스 변수, 그와 관련된 접근자 메서드, 프로퍼티 정의를 같은 규칙 안에 두게 하는 간편 문법이기 때문이다.

카테고리는 데이터를 캡슐화하는 방법이 아닌 클래스의 기능을 확장하는 방법으로 생각해야 한다.



-

읽기 전용 프로퍼티는 때때로 카테고리 내에서 꽤 유용하게 사용될 수 있다.

@impelementation NSCalendar (EOC_Additions)

- (NSArray*)eoc_allMonths{

     if ( [self.calendarIdentifier isEqualToString:NSGregorianCalendar] ){

          return @[@“January”, @“Feburary”, … , @December” ];

     } else if ( /* 다른 달력 */ ){

          ...

     }

}

@end


프로퍼티의 인스턴스 변수에 대한 자동 합성(autosynthesis)은 동작하지 않을 것이다.


위와 같이 읽기 전용을 사용할 수 있다고 하더라도, 카테고리에서의 보통은 프로퍼티를 사용하지 않는 것이 좋다.

프로퍼티는 클래스의 데이터를 저장하고 있는 것이고, 데이터를 캡슐화한다.




기억할 점


데이터를 캡슐화하는 모든 프로퍼티 선언은 메인 인터페이스 파일에서 하라.


클래스 확장 카테고리를 제외하고 카테고리 내에 프로퍼티를 선언하기보다는 접근자 메서드를 사용하라.




반응형

댓글