1

在 iPhone 应用程序上工作,我有一个类实例,该类实例被定义为全局并在 ViewDidLoad 中为 UITableViewController 初始化。

当它到达 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
}

表视图控制器:

测试表视图控制器.h

Foo *foo;

测试表视图控制器.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 中遗漏了一些东西以挂起属性,直到实例被释放?

更新

我发现通过在从数据库填充属性时添加保留,数据包含:

 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;

现在,要实际使用您的属性,请使用 getter 和 setter。这将保留您的价值并在适当的时候释放它。

[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 回答