2010年9月30日木曜日

クラス変数を扱う際にselfつけるか田舎、いや否か

はい、しょーもない出だしでした。

またクラスを定義して考えていくです(・ω・)ノ


<CVImageView.h>
 @interface CVImageView : UIView {
    UIView *menuView;
UILabel *label;
}

//ゲッター、セッター作るよー!という宣言
@property (nonatomic, retain)UIView *view;
@property (nonatomic, retain)UILable *label;
-(void)hoge;

@end

<CVImageView.m> 
@synthesize view;
@synthesize label;

-(void)viewDidLoad//ビルドして一番最初に呼ばれる関数
{
  //初期化
  self.label.text = @"hoge"; ー ①
  label.text = @"hoge"; ー②
}

-(void)hoge
{
/*viewDidLoadで説明しちゃうので略*/
}


さーて、①と②はどういう違いがあるのでしょうか。


(゚ε゚)えっと。。



正解は、
①はゲッター関数を経由して、クラス変数labelを初期化していて、②はゲッター関数を経由しないで初期化しています。

@property, @synthesizeを宣言するということはセッター関数とゲッター関数を自分で宣言せずにおまかせで作ってしまおうということでしたよね。

だから実は、この場合
-(UILabel *)label//getとは頭につけないのがobj-Cの習慣
{
     retrun label;
}
-(void)setlabel:(id)temp
{
   if(label != temp){
      [temp retain];
      [label release]
      label = temp;  
 }
}
が明示的には書かれないけど宣言されています。
だからself.labelとするとこの関数が呼ばれるんですねー。

これが気にいらない場合は@propertyはする一方で, @synthesizeを宣言をせずに、
自分でゲッター、セッター関数を定義するのも手ですね。

-(UILabel *)label
{
     retrun label;

}
実際これだとlabelのテキストが@"hoge"で初期化されてなくても(nilであっても)返ってきてしまうので、少し処理で困る事もあります。

というのは
[(中身がnilのインスタンス) 関数];とコードを書いても、ビルドは通るのですね。
しかし、中身がnilなので、関数は実行されずに無視されてしまうという罠。

だから、ビルドが通ってエラーが出なくても、そこの処理が行われないっていうことも起こりえます。

ここで、より確実に初期化でnilでは無いものを入れて、nilが返ってこないようにするには、 @synthesizeを宣言をせずに、自分で設定してしまいます。

ゲッター関数は以下のように定義します。

-(UILabel *)label
{
   if(!label.text) { //if(A) : if A is not nil labelがnilのとき
        UILabel *tempLabel.text = @"hoge";
        self.label = tempLabel;
   }
   return label; //label.textがnilではない時
}

ってやっちゃえば、確実にtextがnilじゃないものが返ってきますお!!

0 件のコメント:

コメントを投稿