iPhone 自动释放返回的 NSMutableArray

发布于 2024-11-04 06:58:55 字数 1713 浏览 6 评论 0原文

我对 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 不再指示潜在的内存泄漏,但每次代码执行时都会崩溃,说消息已发送到已释放的实例。任何帮助将不胜感激,我花了很长时间在谷歌上搜索,但看不出代码有什么问题。我确实找到了这个线程,但它似乎不是我问题的答案 - 崩溃当 NSMutableArray 返回时会发生什么?

I'm still relatively new to iPhone development but thought I understood the basic principals of memory management. I have a class method that returns an NSMutableArray, I'm calling alloc and init on the object therefore know I'm responsible for releasing it. However because I'm returning the array I assumed I was supposed to use autorelease when creating the object instead of releasing it.

+(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;
}

There's the basic code - XCode no longer indicates a potential memory leak but it crashes everytime that code executes saying message sent to deallocated instance. Any help would be appreciated I've spent ages googling and can't see what's wrong with the code. I did find this thread but it doesn't appear to be the answer to my question - crash happens when NSMutableArray is returned?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

极致的悲 2024-11-11 06:58:55

您发布的代码似乎正确管理内存 - 您在保留和(自动)释放之间有一对一的关系,并且您正在使用自动释放进行教科书使用 - 所以问题是可能调用此方法的代码需要在自动释放池启动并将地毯从您身下拉出之前保留结果数组。

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

@property (retain) NSMutableArray *myStations;

如果您正在执行其他操作来存储数组,则可能需要调用 <代码>[myStations 保留]。您的表视图代码还需要释放该数组,可能是在其dealloc方法中。

The code you've posted appears to be managing memory correctly – you've got a one-to-one relationship between retains and (auto)releases, and you're making a textbook use of autorelease – so the problem is probably that the code calling this method needs to retain the resulting array before the autorelease pool kicks in and yanks the rug out from under you.

If your code is assigning the NSMutableArray to an ivar you've declared with @property, that ivar needs to be declared as

@property (retain) NSMutableArray *myStations;

If you're doing something else to store the array, you may need to call [myStations retain]. Your table view code will also need to release the array, probably in its dealloc method.

葬心 2024-11-11 06:58:55

如果您想使用返回的 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 方法),但是如果类想要在当前事件之后使用它,则需要保留它。

If you want to use the returned NSMutableArray as a data source to fill in rows in a table view, then you're going to need to retain it in your UITableView class (or your UITableViewDataSource delegate class). It's going to be called repeatedly whenever the view is scrolled or otherwise needs updating.

Easiest thing to do is make it a retained property in that class.

@property (nonatomic, retain) Tests * stationArray;

Then, say, if you want to get your data in your viewDidLoad method:

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

Access it in numberOfRowsInSection:

return self.stationArray.count;

Access it in cellForRowAtIndexPath:

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

And, of course, in dealloc...

[stationArray release];

The autorelease in the method is correct (not an init or copy method), but the class will need to retain it if it wants to use it later on, after the current event.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文