假设我有一个名为 MyTestClass.h 的课程。
类结构看起来像
@interface MyTestClass : NSObject {
NSString *testString;
}
@property (nonatomic, retain)NSString * testString;
@end
.m文件
@implementation MyTestClass
@synthesize testString;
-(id) init{
[self setTestString:@""];
return self;
}
-(void)dealloc{
[self.testString release];
testString = nil;
[super dealloc];
}
@end
现在我创建了 MyTestClass 的对象并分配了 testString 两次
MyTestClass * myTestClass = [[MyTestClass alloc] init];
[myTestClass setTestString:@"Hi"];
[myTestClass setTestString:@"Hello"];
现在我想,我的testStrings内存被泄露了两次!! (一个通过 init(),另一个通过我的第一个 setTestString 方法)
我是对的吗?或将@property (nonatomic, retain)
处理/释放以前分配的内存?
或者,在这种情况下,我需要覆盖 MyTestClass.m 中的 setTestString(),如下面的代码
-(void)setTestString:(NSString *)tempString{
[testString release];
testString = nil;
testString = [tempString retain];
}
对此问题的任何帮助表示赞赏。
感谢。
答案 0 :(得分:2)
对此问题的任何帮助表示赞赏。
我会将此作为许可证,使得观察结果不一定与您的问题直接相关。
首先,如果你声明一个retain属性(正如你所做的那样)并对其进行综合,那么自动生成的getter和setter会为你正确处理内存管理。
如果您手动创建setter(即使存在@synthesize
也允许这样做),您必须自己进行内存管理。使用trojanfoe的任何一个例子。
你问题中的setter包含一个错误,如果testString == tempString,即你将属性的值赋给自己,你最终可能会为该属性分配一个悬空指针,因为你有效地释放了tempString然后保留它
这是一个安全忽略的实现细节,但是字符串文字,例如@"blah"
被编译到可执行文件中,无论它们被释放多少次都不会被释放。所以,举个例子,即使setter没有做正确的内存管理,也不会有泄漏。
顺便说一句,init方法的正常模式是
-(id) init
{
self = [super init];
if (self != nil)
{
// init stuff
}
return self;
}
或逻辑等价物。
你应该养成使用它的习惯,因为你需要调用超类的init方法,并允许它改变self的值,甚至是nil。
此外,虽然通常在释放后将对象引用设置为nil是非常好的做法,但在这两种情况下,都是不必要的。第一次,变量即将超出范围,第二次立即从其他对象中分配变量。
答案 1 :(得分:0)
这不是泄漏。正确处理合成变量。
以这种方式实现合成方法(对于retain关键字)
@property (nonatomic, retain) NSString *string;
//backed by variable NSString *_string;
- (void)setString:(NSString*)newString
{
if (newString != _string) {
[_string release];
_string = [newString retain];
}
}
当然这是泄密:
- (void)aMethod //of my class with string property
{
NSString *aString = [[NSString alloc] initWithString:@"hello"];
self.string = aString; //retain count of 2
self.string = @"hello2"; //retain count of 1 for aString
//now I don't release aString.... leak
}
答案 2 :(得分:0)
如果您使用自动生成的setter(在您的情况下,setTestString:
,也由self.testString = ...;
调用),retain
属性的先前值在被设置之前被释放。所以不,您在上面发布的代码中没有泄漏。
答案 3 :(得分:0)
synthesize
d setter方法应该做正确的事情。以下是它的实现示例:
- (void)setTestString:(NSString *)tempString
{
[tempString retain];
[testString release];
testString = tempString;
}
或:
- (void)setTestString:(NSString *)tempString
{
if (tempString != testString)
{
[testString release];
[tempString retain];
testString = tempString;
}
}
答案 4 :(得分:0)
仅在实例被销毁时调用dealloc。 如果你这样做:
[myTestClass setTestString:@"Hi"];
[myTestClass setTestString:@"Hello"];
在同一个区块中,你是两个叫做二传手的人。没有内存泄漏。
答案 5 :(得分:0)
在指定@synthesize
的属性上使用retain
时,生成的setter将正确处理多个赋值的保留/释放。只要您使用self.
而不是直接转到支持变量并在dealloc
中进行最终发布,您应该没问题。