2012-05-06 19 views
10

私はJavaの背景から来て、私はObjective Cを学んでいます。配列を変更するための文字列配列とメンバ関数を持つクラスを作成しようとしています。私のコードは次のようになりました:Objective CでNSMutableArrayを初期化する方法は?

@implementation TAWChapter 

@synthesize mSubject; 

@synthesize mItems; 

- (id) init{ 
    self.mItems = [[NSMutableArray alloc] init]; 
    return self; 
} 

- (void) setSubject:(NSString *)subject{ 
    self.mSubject = subject; 
} 

- (void) addItem:(NSString *)item{ 
    [self.mItems addObject:@"asdf"]; 
} 

@end 

これはうまくいきませんでした。 "[__NSArrayI addObject:]: unrecognized selector sent to instance ""NSInvalidArgumentException"があります。インターネットで検索した結果、コンストラクタの1行を次のように変更しました:

self.mItems = [self.mItems init]; 

なぜですか? Java開発者の視点から見ると、第1のものは第2のものよりも理にかなっています。私は別の行を持っていますが、最初の行と同じですが、それは動作しています(コンストラクタではありません)。誰かが私にこれを説明できますか?

+1

の答えは、おそらく問題に対処してきたが、我々は 'mItems'プロパティの宣言が表示されるまで、我々は確認することはできません。 –

答えて

27
  1. ファーストとりわけ、Objective-Cコーディング規約に従うべきです。 Objective-Cでは、クラスにはコンストラクタがありません。クラスには初期化子があります。 Objective-Cで、初期化子は、スーパークラスのイニシャライザを呼び出し、それは次のようになります。

    - init 
    { 
        self = [super init]; 
        if (!self) return nil; 
    
        // set up other stuff here 
    
        return self; 
    } 
    
  2. 第二に、あなたはARCを使用していない限り、あなたがメモリリークを持っているかもしれません。イニシエータの最初の行は、所有しているオブジェクトを所有権を持つ可能性が高いプロパティに割り当てます。あなたは使用する必要があり、次のいずれか

    // property takes care of ownership 
    self.mItems = [NSMutableArray array]; 
    

    か:

    // assign to instance variable directly with owned object 
    mItems = [[NSMutableArray alloc] init]; 
    

    それはKVOのようなものをいじることができますので、Appleは時々初期化子でのアクセサメソッドの使用を思いとどまらが、アクセサメソッドの一貫した使用が適切なオブジェクトの所有権を確保およびメモリ管理。あなたの初期化子であなたのラインを変更することにより

  3. self.mItems = [self.mItems init]; 
    

    何もしません。initialiserメソッドが呼び出されると(通常、割り当てられた直後)、すべてのインスタンス変数は自動的にnilに設定されます。最初のインスタンスを割り当てることなくinitを使用していない、と何度もinit以上を使用しないでください、

    self.mItems = nil; 
    

    と:

    self.mItems = [nil init]; 
    

    だけです:だから何をやっていることはただです。

  4. スーパークラスを初期化させないと、他の領域で問題が発生することがあります。 Build &を分析し、アナライザーが指摘している問題を修正したことを確認してください。

+0

非常に良い答え:) – MJB

+0

素敵なおかげで:-) – YannickSteph

2

あなたはsuperに電話をかけて、自分のinit方法でselfにその結果を割り当てる必要があります:Objective-CのはCのスーパーセットなので

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.mItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 
6

、それはいくつかの「OO」のシンタックスシュガーとcは、基本的です。オブジェクトを作成(または使用)する前に、そのオブジェクトのヒープ領域を確保する必要があります。 [Class alloc]でこれを行います。次のステップは、そのスペースの初期化です。 allocはヒープ内のその領域へのポインタを返します。これはinitで初期化します)

Class *myObjc = [[Class alloc] init];と呼んでいます。

継承(NSOBjectから継承してから継承する)を使用する場合は、スーパークラスがすべてを適切に初期化していることを確認する必要があります。あなたは、ランタイムエラーを取得し、自己のためにチェックしていないことを確認するために、あなたは(自己)

self.mItems = [self.mItems init]; // doesn't do anything, since you call the getter for mItems with self.mItems and try to init. then you try to set mItmes to itself. 

使用このコードの場合に暗黙的に行う= nilを、:!

@implementation TAWChapter 

@synthesize mSubject, mItems; 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     mItems = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void) setSubject:(NSString *)subject{ 
    mSubject = subject; 
} 

- (void) addItem:(NSString *)item{ 
    [mItems addObject:item]; 
} 

@end 
0

にNSArrayからNSMutableArrayのを作成することができ、別の方法:

NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray]; 
関連する問題