인스턴스 변수를 @implementation블록 또는 클래스 확장 에 넣는 기능은 모든 버전의 iOS 및 64 비트 Mac OS X 프로그램에서 사용되는 "현대적인 Objective-C 런타임"의 기능입니다.
32 비트 Mac OS X 앱을 작성하려면 @interface선언에 인스턴스 변수를 넣어야합니다 . 하지만 앱의 32 비트 버전을 지원할 필요는 없습니다. OS X은 5 년 전에 출시 된 버전 10.5 (Leopard) 이후 64 비트 앱을 지원했습니다.
따라서 최신 런타임을 사용할 앱만 작성한다고 가정 해 보겠습니다. ivar를 어디에 두어야합니까?
옵션 0 : @interface(하지 마세요)
먼저 인스턴스 변수를 선언 에 넣지 않는 이유를 살펴 보겠습니다 @interface.
인스턴스 변수를 배치 @interface하면 클래스 사용자에게 구현 세부 정보가 노출됩니다. 이로 인해 해당 사용자 (자신의 클래스를 사용하는 경우에도 자신도!)가하지 말아야 할 구현 세부 사항에 의존하게 될 수 있습니다. (이것은 우리가 ivars 선언 여부와 무관합니다 @private.)
인스턴스 변수를 삽입 @interface하면 컴파일 시간이 더 오래 걸립니다. ivar 선언을 추가, 변경 또는 제거 할 때마다 .m인터페이스를 가져 오는 모든 파일 을 다시 컴파일해야하기 때문 입니다.
따라서 인스턴스 변수를 @interface. 어디에 두어야합니까?
옵션 2 : @implementation중괄호없이 (하지 마십시오)
다음으로, 옵션 2,“중괄호 블록없이 @implementantion 아래에 iVars 배치”에 대해 논의 해 보겠습니다. 이것은 인스턴스 변수를 선언 하지 않습니다 ! 당신은 이것에 대해 이야기하고 있습니다.
@implementation Person
int age;
NSString *name;
...
이 코드는 두 개의 전역 변수를 정의합니다. 인스턴스 변수를 선언하지 않습니다.
예를 들어 모든 인스턴스가 캐시와 같은 일부 상태를 공유하기를 원하기 때문에 전역 변수가 필요한 경우 .m파일에서도 전역 변수를 정의하는 @implementation것이 좋습니다. 그러나이 옵션은 ivar를 선언하지 않기 때문에 ivar를 선언하는 데 사용할 수 없습니다. (또한, 구현에 전용 전역 변수는 일반적으로 static전역 네임 스페이스를 오염시키고 링크 타임 오류를 방지하기 위해 선언해야 합니다.)
그러면 옵션 1과 3이 남습니다.
옵션 1 : @implementation중괄호 포함 (Do It)
일반적으로 옵션 1을 사용합니다. 다음 @implementation과 같이 중괄호로 기본 블록 에 넣습니다 .
@implementation Person {
int age;
NSString *name;
}
우리는 그것들의 존재를 비공개로 유지하고 앞서 설명한 문제를 방지하고 일반적으로 클래스 확장에 넣을 이유가 없기 때문에 여기에 넣었습니다.
그렇다면 옵션 3을 언제 클래스 확장에 넣어야할까요?
옵션 3 : 수업 연장에서 (필요할 때만 수행)
클래스의 .NET Framework 파일과 동일한 파일의 클래스 확장에 넣을 이유가 거의 없습니다 @implementation. @implementation그런 경우에는 그냥 넣는 게 좋을 것 같습니다 .
그러나 때때로 우리는 소스 코드를 여러 파일로 나누고 싶을만큼 충분히 큰 클래스를 작성할 수 있습니다. 카테고리를 사용하여이를 수행 할 수 있습니다. 예를 들어, UICollectionView(약간 큰 클래스) 구현 하는 경우 재사용 가능한 뷰 (셀 및 보충 뷰)의 큐를 관리하는 코드를 별도의 소스 파일에 넣기로 결정할 수 있습니다. 이러한 메시지를 범주로 분리하여이를 수행 할 수 있습니다.
@interface UICollectionView : UIScrollView
- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
@property (nonatomic, retain) UICollectionView *collectionViewLayout;
@end
@interface UICollectionView (ReusableViews)
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier;
- (void)registerClass:(Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier;
- (id)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
- (id)dequeueReusableSupplementaryViewOfKind:(NSString*)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
@end
이제에서 기본 UICollectionView메서드를 UICollectionView.m구현할 수 있고에서 재사용 가능한 뷰를 관리하는 메서드를 구현할 수 있으므로 UICollectionView+ReusableViews.m소스 코드를 좀 더 쉽게 관리 할 수 있습니다.
그러나 재사용 가능한 뷰 관리 코드에는 몇 가지 인스턴스 변수가 필요합니다. 이러한 변수는의 메인 클래스 @implementation에 노출되어야 UICollectionView.m하므로 컴파일러는 .o파일 에서 변수 를 내 보냅니다 . 또한 이러한 인스턴스 변수를의 코드에 노출해야 UICollectionView+ReusableViews.m해당 메서드가 ivar를 사용할 수 있습니다.
여기에 클래스 확장이 필요합니다. 재사용 가능한보기 관리 ivar를 개인 헤더 파일의 클래스 확장에 넣을 수 있습니다.
@interface UICollectionView () {
NSMutableDictionary *registeredCellSources;
NSMutableDictionary *spareCellsByIdentifier;
NSMutableDictionary *registeredSupplementaryViewSources;
NSMutableDictionary *spareSupplementaryViewsByIdentifier;
}
- (void)initReusableViewSupport;
@end
이 헤더 파일은 라이브러리 사용자에게 제공되지 않습니다. 이 ivar를 보는 데 필요한 모든 항목이 볼 수 있도록 에서 UICollectionView.m및에서 가져 오기만하면 됩니다. 또한 재사용 가능한 뷰 관리 코드를 초기화하기 위해 메인 메서드가 호출 할 메서드를 던졌습니다 . 우리는에서 해당 메소드를 호출 할 수 있습니다 에서 , 우리는 그것을에서 구현하는 것이다 .UICollectionView+ReusableViews.minit-[UICollectionView initWithFrame:collectionViewLayout:]UICollectionView.mUICollectionView+ReusableViews.m