iPhoneアプリのメモリ管理 その1で、リファレンスカウンタ方式のメモリ管理の事を、iPhoneアプリのメモリ管理 その2でautoreleasepoolの事を書きました。
その3は@propertyです。
@propertyとメモリ管理の話をする前に、オブジェクト指向の基本的な考え方であるカプセル化についての理解が必要です。
オブジェクトとは、データと手続きをある単位でまとめたものですが、オブジェクトの独立性を高める為に、オブジェクトの内部構造を隠蔽する事がカプセル化です。
例えば、車を表すオブジェクト(クラス)が有ったとして、ガソリンの残量、消費量、走行距離、燃費のデータを管理しているとします。
燃費のデータは、外部のクラスからは取得/参照は自由に行っても問題となりませんが、自由にセットされると、走行距離やガソリンの消費量などの他のデータと矛盾が起きます。
こういった事が起きないよう、値を取得するメソッド(getterメソッド)や、値を設定するメソッド(setterメソッド)を設けて、カプセル化します。
getterとsetterというインターフェイスを設けて、内部の値を隠蔽する(カプセル化する)メリットとしては、燃費の場合は参照は許しても、設定は許さないという状況にしたい場合は、getterのみ設けてsetterを設けないとか、ガソリンのsetterメソッドでは、内部で管理している燃費も再計算するという事ができるようになります。
この思想自体はいいとして、外部のクラスに公開する変数を設けるたびに、getter/setterのコードを書くとなると、大したコードではないのに、手間はかかるという状況になって、生産性が低くなってきます。
ここで@propertyの登場です。
Jave言語でのプログラミング経験があって、JaveBeansを作った事がある人なら、ここまででピンと来たかも知れません。
Objective-Cでは、@propertyを使うと、自動的にsetter/getterを設けたり、getterだけ設けたりといった事だけでなく、setterでセットするオブジェクトに対して何をするかまで指定できます。
例えば、Somethingクラスのint型のvalue変数に対して、
@property (nonatomic, readonly) int value;
とすれば、getterメソッドが作られます。
自前でgetterメソッド(getValue)を定義したとした場合は、以下のよな記述になりますが、
Something *ins = [Something alloc];
int val = [ins getValue];
@propertyを使用して定義した場合は、ドットシンタックスで、あたかも変数を直接参照しているかのような書き方でアクセスできます。
int val = ins.value;
これはsetterメソッドでも同様です。
@property (nonatomic, assign) int value;
とした場合は、
ins.value = 1;
と記述できます。
プリミティブな型(int,double,floatなど)であれば、ここで話は終わりですが、オブジェクトの場合は、さらに動作を指定できます。
@property (nonatomic, assign) Something *ins;
@property (nonatomic, copy) Something *ins;
@property (nonatomic, retain) Something *ins;
前フリが長くなりましたが、このretainやcopyがちょっとくせ者です。
retainやcopyで定義されている変数にオブジェクトを設定した場合、リファレンスカウンタがひとつ上がります。
なんらかの理由でreleaseが漏れていると、メモリにゴミが残って行く事になります。
自前のクラスで@propertyを使っている場合は注意が必要です。
例えば、value変数をretainで定義した場合、クラス内で変数を参照するときに、
value = something; // ( 1 )
と書くか、
ins.value = something; // ( 2 )
と書くかで意味が変わってきます。
( 1 )は直接代入している為、リファレンスカウンタに影響は有りませんが、( 2 )ではカウンタが増える為、releaseを忘れていると、解放していないメモリ領域がゴミとして残る事になります。
iPhoneのAPIについても、自分が使用している変数がどのように定義されているかを理解した上で使った方が安全です。
APIリファレンスには「Properties」という項目が有りますが、ここで各変数を見ると、@propertyの定義も書かれています。
ここでretainやcopyで定義されているものについては、何かしらreleaseの為の処理が必要かも知れないので、注意する必要が有ります。
@propertyは、Objective-Cの特徴的な機能なので、しっかりと理解しておいた方がいいですが、今回はここまでにして、参考となるページを以下に記載しておきます。
ダイナミックObjective-C プロパティ(2) – プロパティの宣言
ダイナミックObjective-C プロパティ(3) – ドット演算子
ダイナミックObjective-C プロパティ(4) – プロパティの属性
※Appleのドキュメント「The Objective-C 2.0 Programming Language」の「Declared Properties」という項目に詳細な説明があります。
※iPhoneアプリ開発に関する投稿を今から始めるiPhoneアプリ開発にまとめました。
最近のコメント