【问题标题】:IPhone autoreleasing a returned NSMutableArrayiPhone 自动释放返回的 NSMutableArray
【发布时间】:2011-08-17 05:14:54
【问题描述】:

我对 iPhone 开发还比较陌生,但我认为我了解内存管理的基本原理。我有一个返回 NSMutableArray 的类方法,我在对象上调用 alloc 和 init,因此知道我负责释放它。但是,因为我要返回数组,所以我认为我应该在创建对象时使用 autorelease 而不是释放它。

+(NSMutableArray *)getStations:(int)stationType {

if(database == nil){
    [self openDataBase];
}

// Create a temporary array to hold the returned objects
NSMutableArray *holder = [[[NSMutableArray alloc] init] autorelease];

// Check if the statement has been defined
if(select4 == nil) {

    const char *sql = "SELECT station_id, station_name, AVG(test_percent) FROM stations LEFT JOIN tests USING (station_id) WHERE station_type = ? GROUP BY station_id ORDER BY station_name ASC";

    if(sqlite3_prepare_v2(database, sql, -1, &select4, NULL) != SQLITE_OK){
        NSLog(@"Error while creating detail view statement. '%s'", sqlite3_errmsg(database));
    }
}

sqlite3_bind_int(select4, 1, stationType);

// Check if the statement executed correctly
while(sqlite3_step(select4) == SQLITE_ROW) {

    NSInteger primaryKey = sqlite3_column_int(select4, 0);
    Tests *station = [[Tests alloc] initWithPrimaryKey:primaryKey];
    station.station_name = [NSString stringWithUTF8String:(char *)sqlite3_column_text(select4, 1)];
    station.average_score = [NSNumber numberWithDouble:sqlite3_column_double(select4, 2)];

    [holder addObject:station];
    [station release];
}

// Reset the detail statement.
sqlite3_reset(select4);

// Return the holder array
return holder;
}

有基本代码 - XCode 不再指示潜在的内存泄漏,但每次执行该代码时都会崩溃,说消息发送到已释放的实例。任何帮助将不胜感激我花了很长时间谷歌搜索并且看不出代码有什么问题。我确实找到了这个帖子,但它似乎不是我问题的答案 - crash happens when NSMutableArray is returned?

【问题讨论】:

  • 在这个方法内部还是在这个方法之后崩溃了?
  • 告诉我们崩溃的情况——它发生在哪里以及控制台中显示的错误消息是什么?调用这个方法的代码是什么样的?
  • 在此方法之后,当表视图调用返回数组的计数时 - 但如果我删除自动释放它工作正常(除了“潜在的内存泄漏”警告。错误消息是:-[__NSArrayM count]:消息发送到已释放实例 0x5d75a00
  • @user734971:如果从初始化中去掉autorelease,使用return [holder autorelease];,还会出现崩溃吗?
  • @EvanMulawski 是的,我试过了,但仍然发生崩溃。

标签: iphone memory-management return autorelease


【解决方案1】:

您发布的代码似乎正确地管理了内存 - 您在保留和(自动)释放之间建立了一对一的关系,并且您正在教科书般地使用自动释放 - 所以问题是可能调用此方法的代码需要 retain 生成的数组,然后自动释放池启动并从你下面拉出地毯。

如果您的代码将 NSMutableArray 分配给您使用 @property 声明的 ivar,则该 ivar 需要声明为

@property (retain) NSMutableArray *myStations;

如果您正在做其他事情来存储数组,您可能需要调用[myStations retain]。您的表格视图代码还需要释放数组,可能在其dealloc 方法中。

【讨论】:

    【解决方案2】:

    如果您想使用返回的NSMutableArray 作为数据源来填充表格视图中的行,那么您需要将其保留在您的UITableView 类(或您的UITableViewDataSource 委托类)中)。每当视图滚动或需要更新时,都会重复调用它。

    最简单的做法是使其成为该类中的保留属性。

    @property (nonatomic, retain) Tests * stationArray;
    

    然后,如果你想在viewDidLoad 方法中获取数据:

    self.stationArray = [self getStations: self.stationID]; // property retains
    

    numberOfRowsInSection访问它:

    return self.stationArray.count;
    

    cellForRowAtIndexPath访问它:

    Tests *station = [self.stationArray objectAtIndex:indexPath.row];
    

    当然,在 dealloc 中...

    [stationArray release];
    

    方法中的 autorelease 是正确的(不是 init 或 copy 方法),但是如果要在当前事件之后使用它,类将需要保留它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-19
      • 2011-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多