1

グローバルとして定義され、UITableViewControllerのViewDidLoadで初期化されたクラスインスタンスがあるiPhoneアプリでの作業。

cellForRowAtIndexPathに到達すると、インスタンスプロパティの割り当てが解除され、デバッガーのように表示されます。

プロパティはデータベースからロードされています。

Foo.h

NSString *prop1;

@property(nonatomic, retain)NSString *prop1;
-(void)shouldLoadProperties;

Foo.m

@synthesize prop1;

-(void)shouldLoadProperties {
    <FMDatabase stuff here>

    FMResultSet *rs = [self executeQuery:sql];
    prop1 = [rs stringForColumn:@"col1"];  //loads db value "Test" into prop1
}

テーブルビューコントローラー:

TestTableViewController.h

Foo *foo;

TestTableViewController.m

-(void)viewDidLoad {
   foo = [[[Foo alloc] init] retain];
   [foo shouldLoadProperties];

   //Breakpoint here shows that foo.prop1 is set to "Test"

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   //foo is is still allocated, but foo.prop1 has been 
   //deallocated;  shows as <freed object>  

  NSLog(@"Prop 1 is %@", foo.prop1);  //throws exception


}

私はfooをリリースしていませんが、なぜプロパティはそれ自体の割り当てを解除するのでしょうか?インスタンスがリリースされるまでプロパティにぶら下がる何かがFooにありませんか?

アップデート

データベースからプロパティを設定するときにretainを追加することで、データが保持されることがわかりました。

 prop1 = [[rs stringForColumn:@"col1"] retain];

これは正しいですか、それとも私は何か他のものが欠けていますか?

4

1 に答える 1

1

ここでの問題はprop1、プロパティとしてではなく、クラス内の変数として使用していることです。これらの異なる名前を付けることができ、またそうすべきです。変数名の先頭にアンダースコアを付けるのが通例です。

foo.h

NSString *_prop1;

@property(nonatomic, retain)NSString *prop1;
-(void)shouldLoadProperties;

foo.m

@synthesize prop1 = _prop1;

ここで、実際にプロパティを使用するには、ゲッターとセッターを使用します。これにより、価値が保持され、必要に応じて解放されます。

[self setProp1:[rs stringForColumn:@"col1"]];  //loads db value "Test" into prop1

self.prop1 = [rs stringForColumn:@"col1"];  //loads db value "Test" into prop1

有効であり、互いに同等です。

_prop1 = [rs stringForColumn:@"col1"];  //loads db value "Test" into prop1

クラッシュやその他の悪い動作につながります。

アップデートはクラッシュを防ぎますが、複数回行うとメモリリークが発生します。

于 2012-04-12T22:45:41.463 に答える