iOS / ManagedObjectContext中的内存管理

时间:2011-01-16 11:25:39

标签: objective-c ios memory-leaks autorelease convenience-methods

看起来我不理解Objective C中的内存管理......叹息。

我有以下代码(请注意,在我的情况下,placemark.thoroughfareplacemark.subThoroughfare都填充了有效数据,因此if - 条件都将为TRUE < / p>

itemManagedObjectContext绑定。 item中的托管变量(例如place)使用@dynamic创建了设置者/获取者。因此,声明是

@property (nonatomic, retain) NSString *place;
@dynamic place;

稍后在代码中,在ReverseGeocoderDelegate中,我访问它:

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {

if (placemark.thoroughfare) {
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];        
} else {
    [item.place release];
    item.place = @"Unknown Place";
}
if (placemark.thoroughfare && placemark.subThoroughfare) {
// *** problem is here ***
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}

如果我没有在代码中的标记位置释放item.place,那么Instruments会在那里发现内存泄漏。如果我这样做,一旦我尝试在有问题的方法之外访问item.place,程序就会崩溃。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

首先,我会改变这样的逻辑:

NSString *newPlace = nil;

if (placemark.thoroughfare && placemark.subThoroughfare) {
    newPlace = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
else {
    if (placemark.thoroughfare) {
        newPlace = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
    }
    else {
        newPlace = @"Unknown Place";
    }
}

item.place = newPlace;    // Either nil of valid string can be assigned to

许多人不推荐使用release来简单地重新初始化指针。如果是为了节省一些内存,则不必这样做。

您之前的逻辑确实发布了两次。什么版本最初只是递减retainCount。如果为0,则取消分配对象。在retainCount为0之前,不会释放对象。

假设的属性保留,并且stringWithFormat:返回autoreleased字符串,那么在第二版中,您试图发布无论如何,将会是autoreleased

多次清除对象的最佳方法是简单地为其分配nil

答案 1 :(得分:1)

一个起点是重新阅读有关属性的内容,因为您不需要在任何地方执行`[item.place release]'。所以你可以删除它们。运行时创建的动态代码使该属性能够自动处理释放先前分配给它的任何内容。

此外,[NSString stringWithFormat:...创建了一个自动释放对象(不知道你是否知道:-)这意味着如果你手动管理变量(不是属性)的内存,那么你必须保留/释放它。但是因为你正在使用属性,所以你没有。

我不明白为什么乐器会发现内存泄漏。也许一些更高的代码与它有关。例如,如果你去了item.place = [NSString alloc] initWith...];那么我认为你需要它。

我怀疑是因为释放导致保留计数为零并触发exec错误访问错误。

希望有所帮助。