Objective c iOS/ManagedObjectContext中的内存管理
看来我不了解客观世界中的内存管理。。。唉 我有以下代码(请注意,在我的例子中,Objective c iOS/ManagedObjectContext中的内存管理,objective-c,ios,memory-leaks,autorelease,convenience-methods,Objective C,Ios,Memory Leaks,Autorelease,Convenience Methods,看来我不了解客观世界中的内存管理。。。唉 我有以下代码(请注意,在我的例子中,placemark.throughtree和placemark.subthroughtree都填充了有效数据,因此if-条件都将TRUE item绑定到一个ManagedObjectContext。item中的托管变量,如place具有使用@dynamic创建的setter/getter。因此,声明是 @property (nonatomic, retain) NSString *place; @dynamic pla
placemark.throughtree
和placemark.subthroughtree
都填充了有效数据,因此if
-条件都将TRUE
item
绑定到一个ManagedObjectContext
。item
中的托管变量,如place
具有使用@dynamic
创建的setter/getter。因此,声明是
@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];
}
如果我不释放项。将
放在代码中标记的位置,Instruments会在那里发现内存泄漏。如果我释放,程序会在我尝试访问项时立即崩溃。将
放在有问题的方法之外
有什么想法吗?一个起点是重新阅读属性,因为您不需要在任何地方执行“[item.place release]”。这样您就可以删除它们。运行时为启用该属性而创建的动态代码会自动处理释放以前分配给它的任何内容 另外,
[NSString stringWithFormat:…
会创建一个自动释放对象(不确定您是否知道:-),这意味着如果您手动管理变量(而不是属性)的内存,则必须保留/释放它。但因为您使用的是属性,所以您不需要
我不明白为什么instruments会发现内存泄漏。可能是更高层的一些代码与此有关。例如,如果您使用item.place=[NSString alloc]initWith…];
,那么我认为您将需要它
我怀疑这次崩溃是因为释放导致retain计数为零,并触发exec bad访问错误
希望对您有所帮助。重新阅读属性是一个起点,因为您不需要在任何地方执行“[item.place release]”。这样您就可以删除它们。运行时创建的动态代码用于启用该属性,自动处理释放以前分配给它的任何内容 另外,
[NSString stringWithFormat:…
会创建一个自动释放对象(不确定您是否知道:-),这意味着如果您手动管理变量(而不是属性)的内存,则必须保留/释放它。但因为您使用的是属性,所以您不需要
我不明白为什么instruments会发现内存泄漏。可能是更高层的一些代码与此有关。例如,如果您使用item.place=[NSString alloc]initWith…];
,那么我认为您将需要它
我怀疑这次崩溃是因为释放导致retain计数为零,并触发exec bad访问错误
希望这能有所帮助。首先,我要改变逻辑如下:
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,对象才会被释放
假设您的项目具有属性retain,并且由于stringWithFormat:
返回自动删除
字符串,因此在第二个版本中,您尝试释放将要发布的自动删除
多次清除一个对象的最佳方法是简单地将
nil
赋值给它。首先,我要更改如下逻辑:
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,对象才会被释放
假设您的项目具有属性retain,并且由于stringWithFormat:
返回自动删除
字符串,因此在第二个版本中,您尝试释放将要发布的自动删除
多次清除对象的最佳方法是简单地将
nil
赋值给它。粘贴place
属性的声明以及其setter方法的定义(如果有)会很有用。你是说你用@synthesis
生成了getter/setter吗?我使用了@dynamic,因为我知道这对于绑定到ManagedObjectContext的属性是正确的,就像在我的例子中一样粘贴place
属性的声明以及其setter方法的定义(如果有的话)会很有用。你的意思是你用@synthesis
生成了getter/setter吗?我使用了@dynamic,因为我知道这对于绑定到ManagedObjectContext的属性是正确的,就像我的案例一样。是的,我应该在问题描述中更详细一点。添加了更多信息。很好。但我认为我的注释仍然适用。看起来t您正在“过度管理”。请从删除所有版本开始。托管对象上下文将处理属性的代码,并将正确管理它。'但因为您正在使用属性,所以您不会。'→ 当然,不总是这样。如果它是一个赋值属性(而赋值是一个默认属性),那么他仍然需要管理内存,尽管这不是一个好主意。而且,他可能有一个自定义setter。@bavarieve-true。我忘了提到我假设属性是用retain属性设置的。只检查了我的一个项目,核心数据生成的类在属性上设置了retain所以希望我的评论是正确的