2009-08-03 12 views
7

私はobjective-cにはかなり新しく、iphone用の小さなアプリケーションを作成しようとしています。
私はここでこの小さなエラーの横にほとんどいます。実際には、私は適切な解決策を見つけるためにGoogleで数時間を探しましたが、残念ながら私は動作する解決策を見つけることができません。
私はのUITableViewを構築するためにここにこのチュートリアルを使用しています:objective-c "不変オブジェクトに送信された突然変異メソッド"エラー

*キャッチされない例外により「NSInternalInconsistencyException」、理由にアプリを終了:UITableView Tutorial 完全なエラーメッセージは、次のようになります「* - [ NSCFArrayは、insertObject:atIndex:]:不変オブジェクトに送られた変異法」

これは、データコントローラヘッダーです: MyLinksDataController.h

@interface MyLinksDataController : NSObject { 

NSMutableArray *tableList; //<---important part 

} 

- (unsigned)countOfList; 
- (id)objectInListAtIndex:(unsigned)theIndex; 
- (void)addData:(NSString *)data; //<---important part 
- (void)removeDataAtIndex:(unsigned)theIndex; 

@property (nonatomic, copy, readwrite) NSMutableArray *tableList; //<---important part 

..... 

とデータコントローラ方法: MyLinksDataController.m

#import "MyLinksDataController.h" 

@implementation MyLinksDataController 

@synthesize tableList; 

- (id)init { 

    if (self = [super init]) { 

     NSLog(@"Initilizing DataController"); 
     //Instantiate list 
     NSMutableArray *localList = [[NSMutableArray alloc] init]; 
     self.tableList = [localList copy]; 
     [localList release]; 

     //Add initial Data 
     [self addData:@"AAAAAAAAAAAAAA"]; 
     [self addData:@"BBBBBBBBBBBBBB"]; 

    } 

    return self; 

} 

----------------------------- - 後でソースコードで---------------------------------

- (void)addData:(NSString*)data; { 

    [tableList addObject:data]; //<---- here the app crashes 

} 

私はどんな助けにも大変感謝しています。

ご協力いただきありがとうございます。次の文のようにのinitに - - ダニエル

答えて

27

NSMutableArrayのにコピーメッセージを送信

は不変のコピーを返します。

self.tableList = [localList copy]; 

ココアドキュメントはcan't-変更することが、後の初期化オブジェクト、読み取り専用参照する単語不変を使用します。したがって、addObject:への下位呼び出しが失敗し、エラーメッセージが表示されます。

上記の代入文がコンパイラの警告をどのように引き起こさないかに注意してください。 コピーは、idを返します。これは、コンパイラに関する限り、NSMutableArray * tableListに快適に適合します。メッセージがまったく渡されないので、ここにランタイムエラーもありません。 NSArrayポインタはNSMutableArrayポインタ変数に置かれます。

可変コピーを取得するには、代わりにmutableCopyを使用してください。 コピーの両方mutableCopyは、新しい配列を作成して、オリジナルのコンテンツをコピー

注意。コピーの変更はオリジナルに反映されません。元の配列への別の参照が必要な場合は、の代わりにを使用してください。

詳細については、copyWithZone referenceNSMutableCopying protocol referenceのディスカッションセクションを参照してください。

5

基本的には、Cocoa(specifically, these details)のメモリ管理ルールに慣れています。 immutable versionと変更可能なバージョンのオブジェクトがある場合、-copyをオブジェクトに送信すると、不変オブジェクトが返されます。

関連する部分をステップアップしましょう。

NSMutableArray *localList = [[NSMutableArray alloc] init]; 

これは、所有する新しい空の可変配列を作成します。ファイン。

self.tableList = [localList copy]; 

これは空の配列の不変コピーを作成します。さらに、あなたはこの新しく作成されたコピーを所有しています。それはあなたが現在所有している2つのオブジェクトです。

これは、コピーしたオブジェクトをtableListプロパティに割り当てます。

@property (nonatomic, copy, readwrite) NSMutableArray *tableList; 

このプロパティはcopy attributeと宣言されているので、新しい値がそれに割り当てられている時はいつでも、別の-copyの方法は、それに送信されますのは、プロパティの宣言を見てみましょう。しかし、この3番目のコピーは所有者ではなく、オブジェクトが所有しています。

元の空の可変配列を解放します。ファインですが、未だに浮かんでいる2行目に浮かんだものがまだあります。それはメモリリークです。

実際に変更可能なコピーが必要な場合は、-mutableCopyメソッドが必要です。 (これらのメソッドのドキュメントはNSCopyingNSMutableCopyingの下にあります)。copy属性を持つプロパティに変更可能なバージョンを取得することは決してありません。割り当てられているものに-copyを送信するためです。あなたの財産ではなくcopy属性のretain属性を使用する必要があり、それを初期化するコードは次のようになります。

NSMutableArray *localList = [[NSMutableArray alloc] init]; 
self.tableList = localList; 
[localList release]; 

か、短いバージョン:

self.tableList = [NSMutableArray array]; 

コピーする必要はありませんがこのような状況では、新しいオブジェクトを作成するだけです。

+1

コピープロパティが実際に呼び出された場合は、保持してプロパティを代入することは貧しいソリューションになるだろう。 mutablecopyキーワードがないので、プロパティをコピーとして宣言しますが、合成されたアクセサを使用するのではなく、独自のアクセサを記述してください。 –

+0

良い点。私は 'NSMutableArray'プロパティを宣伝するオブジェクトをほとんど見たことがないことも忘れてしまいます。私の中の純粋主義者は、オブジェクトの可変コピーを格納するカスタムセッターと、オートレリースされた不変コピーを返すカスタムゲッターを見たいと思うでしょう。 –

0

こんにちはmutableCopyの代わりに私はこの問題に取り組むために "strong"を使うこともできると信じています。 "strong"の代わりに "copy"を使用したため、同様の問題が発生しました。だから、下の行:

@property (copy, nonatomic) NSMutableArray *computers; 

は、それは次のようになります。

@property (strong, nonatomic) NSMutableArray *computers; 

それは私のような過ちを犯して初心者のための巨大な助けになることを願っています。

1

他のオブジェクトからlocalListを割り当てている場合は、そのような場合にはこの種のエラーが発生する可能性があります。

私はそれが役に立ちそうです。

self.tableList = [localList mutableCopy]; 
0

これは、問題を解決します:

NSMutableArray *localList = [[NSMutableArray alloc] init]; 
self.localList = [[NSMutableArray alloc]initWithArray:localList]; 
関連する問題