西海岸より

つらつらざつざつと

簡単なprivateなsetterメソッドの実装方法

Objective-Cでは、プロパティの機能で以下のように記述することで、自動にアクセサメソッドを生成してくれるが、セッターは外部から非公開としたい、ということがよくある。

@property(retain) NSArray *array;
@synthesize array;

ここで、@property(retain, readonly)としてしまうと、ローカルからもセットできなくなってしまう。
なので、以下のようにセッターを.mファイルの中で、自分で実装する必要があります。

  • Sample.h
#import <Foundation/Foundation.h>

@interface Sample : NSObject {
 @private
  NSArray *array_;
}
@property (nonatomic, retain, readonly) NSArray *array;

@end
  • Sample.m (面倒くさい実装)
#import "Sample.h"

@interface Sample ()
- (void)setArray:(NSArray *)newArray;
@end

@implementation Sample
@synthesize array=array_;
- (void)setArray:(NSArray *)newArray {
  if (array_ != newArray) {
    [array_ release];
    array_ = [newArray retain];
  }
}
- (void) dealloc {
  [array_ release];
  [super dealloc];
}
@end

プロパティにより自動生成してくれたメソッドを自分で書かなくてはいけなくなり、結構記述量が増えてめんどうくさい。
もっと簡単な方法はないもんかな、と.mの方のinterfaceの中でpropertyを実装してみるといけた。。。たぶんこれが一番簡単。

  • Sample.m (簡単な方)
#import "Sample.h"

@interface Sample ()
@property (nonatomic, retain) NSArray *array;
@end

@implementation Sample
@synthesize array=array_;

- (void) dealloc {
  [array_ release];
  [super dealloc];
}

@end

これで、以下のような実装を外部クラスで実装した場合に、コンパイル時に警告を出してくれます。

  Sample *sample = [[Sample alloc] init];
  [sample setArray:anArray];  //ここで警告を出してくれる(実行はできてしまいます)

もっと早く気づいていれば。。
ちなみにヘッダファイルの方ではproperty定義の代わりに、以下のようにメソッド定義へ変える必要があります。

  • Sample.h(簡単な方)
- (NSArray *) array;