TableViewControllerに(EXC_BAD_ACCESS)を誤動作オブジェクトのObjective-Cのアレイ
-
09-09-2019 - |
質問
私は、Objective-Cのに新たなんだ、と自動車用オブジェクトの私の配列内のNSStringオブジェクトがリリースされているように見える理由を私は理解することはできません。
ここに私のCar.mクラスです。
#import "Car.h"
@implementation Car
@synthesize categoryId;
- (id)initWithPrimaryKey:(NSInteger)pk categoryId:(NSNumber *)catId carName:(NSString *)n {
if (self = [super init]) {
primaryKey = pk;
categoryId = catId;
name = n;
}
return self;
}
- (void)dealloc {
[name release];
[categoryId release];
[super dealloc];
}
- (NSInteger)primaryKey {
return primaryKey;
}
- (NSString *)name {
return name;
}
- (void)setName:(NSString *)aString {
if ((!name && !aString) || (name && aString && [name isEqualToString:aString])) return;
[name release];
name = [aString copy];
}
@end
そして、ここに私のSimple_TableViewController.mクラスです。 listDataプロパティのインスタンス変数は)(のviewDidLoadで正しく設定されています。デバッガでは、各配列要素のNSStringの*名プロパティはそのままです。その後、他のすべての方法では、listDataプロパティが壊れています。それは正しいPRIMARYKEYと区分値を持つすべての車の要素を持っていますが、NSStringの*名プロパティが「無効な。」
#import "Simple_TableViewController.h"
@implementation Simple_TableViewController
- (void)viewDidLoad {
NSMutableArray *array = [[NSMutableArray alloc] init];
Database *database = [Database instance];
array = [database getAllCars];
[self setListData:array];
[array release];
}
- (NSMutableArray *)listData {
return listData;
}
- (void)setListData:(NSMutableArray *)newListData {
if (listData != newListData) {
[listData release];
listData = [newListData mutableCopy];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[listData release];
[super dealloc];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [listData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
Car *car = [listData objectAtIndex:row];
cell.text = car.name;
cell.font = [UIFont boldSystemFontOfSize:17];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView
indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 0;
}
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
if (row == 0) {
return nil;
}
return indexPath;
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSString *message = [[NSString alloc] initWithFormat:@"You selected %@", [[listData objectAtIndex:row] name]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Row Selected!"
message:message
delegate:nil
cancelButtonTitle:@"Yes I Did"
otherButtonTitles:nil];
[alert show];
[message release];
[alert release];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 35;
}
@end
私はゾンビでこれをいじって、私の指が落ちたまでのことを保持してきました。私は@property(アトミック、保持)とlistDataプロパティ変数の@synthesizeものと離れていた、と私はまだ同じ問題を抱えてます。
あなたが提供しなければならない何かアドバイスを事前に感謝!
解決
あなたのinitWithPrimaryKeyで:など:方法、あなたは(彼らが保持キーワードで宣言されたプロパティと仮定)、それらの値を保持し、またはそれらを割り当てるには、ドット表記を使用する必要があります。これを試してください:
- (id)initWithPrimaryKey:(NSInteger)pk categoryId:(NSNumber *)catId carName:(NSString *)n {
if (self = [super init]) {
primaryKey = pk;
categoryId =[catId retain];
name = [n retain];
}
return self;
}
また、これは単にスタイルの問題であり、あなたが考えるかもしれません。のわずかの「N」と「PK」より多くの冗長な名前。あなたの未来の自己はあなたに感謝します。
他のヒント
ちょっとオフトピック - ベンは、あなたが探している答えを持っていますが、あなたのコードのいくつかのロジックは少し曲がりくねったです。
。- (void)setName:(NSString *)aString {
if ((!name && !aString) || (name && aString && [name isEqualToString:aString])) return;
[name release];
name = [aString copy];
}
あなたは本当に(!name && !aString)
をチェックする必要はありません。それがnilの上nilを再割り当てするとnilに解放メッセージ(または任意のメッセージ)を送信するために、安全かつ一般的な方法です。後者とオプティマイザランタイム短絡は、前者を削除します。 nilの名前を設定すると、エラーの場合は、aStringのは、
同様に、NSStringsは非常によくoptimiedされています。すでに設定されている名前に車の名前を設定している場合を最適化する気にしないでください。 Infactは、あなたが毎回誰かを取るあなたのチェック[name isEqualToString:aString]
が非nilの文字列は、リリースよりも遅く設定し、少数の症例で回避されているコピーします。
あなたはNSStringのにコピーを送信するときに何が起こるかを確認した場合、あなたはそれだけで、カウントを保持増加見つけることができます。これは明白な理由のためにNSMutableStringのために真実ではないことに注意してください; - )
親指の良いルール - 。あなたはすべての機能を持っているだけ遅い(または大きい)であるものを最適化する際に最適化
最後に、命名についてベンのコメントに続く、私はaCarNameまたは他のより説明的なものにaStringの名前を変更したい - もう一度、あなたの未来の自己はあなたに感謝します。
。