Iphone 目标C中的内存管理?

Iphone 目标C中的内存管理?,iphone,memory-management,Iphone,Memory Management,我有两个属性NSString,这两个属性我已经合成并且是只读的,因此我不能使用property方法self。但我认为这两个传递的字符串都应该保留。因此,我添加了retain以保留属性。但是我觉得,由于传递的对象增加了它们的保留计数,所以这里会有泄漏。但是我的属性会保留这些字符串而不发送消息吗 -(void)setValue:(NSString *)passedString1 second:(NSString *)passedString2{ myString = [passedStri

我有两个属性NSString,这两个属性我已经合成并且是只读的,因此我不能使用property方法self。但我认为这两个传递的字符串都应该保留。因此,我添加了retain以保留属性。但是我觉得,由于传递的对象增加了它们的保留计数,所以这里会有泄漏。但是我的属性会保留这些字符串而不发送消息吗

-(void)setValue:(NSString *)passedString1 second:(NSString *)passedString2{
     myString = [passedString1 retain];
     hisString = [passedString2 retain];
}
假设我将数组(变量)的属性声明为NSArray,并以这种方式传递NSDictionary作为参数

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"text", @"This is some text", nil];
[self setValueForArray:dict];

-(void)setValueForArray:(NSDictionary*)passedDict{
 NSArray *someArray = [NSArray arrayWithObject:passedDict];
 if(array!=someArray){
 [array release];
 array = someArray; //I dont think I should retain this property here since it is retained by someArray
 }
}

此方法是否适用于NSDictionary和NSArray类型。

对字符串使用
copy
,然后释放上一个对象:

-(void)setValue:(NSString *)passedString1 second:(NSString *)passedString2
{
     if (myString != passedString1)
     {
         [myString release]; 
         myString = [passedString1 copy];
     }

     if (hisString != passedString2)
     {
         [hisString release];
         hisString = [passedString2 copy];
     }
}

如果需要
释放作为参数传入的字符串,请在调用
setValue:

后在调用方法中执行该操作,使用
复制字符串并释放上一个对象:

-(void)setValue:(NSString *)passedString1 second:(NSString *)passedString2
{
     if (myString != passedString1)
     {
         [myString release]; 
         myString = [passedString1 copy];
     }

     if (hisString != passedString2)
     {
         [hisString release];
         hisString = [passedString2 copy];
     }
}
如果需要
释放
作为参数传入的字符串,请在调用
setValue:

是后在调用方法中执行此操作,如果这样做,您的属性(更准确地说,与属性对应的实例变量)将保留传递的字符串。但是,还必须确保在指定新值时释放以前的值。例如:

- (void)setValue:(NSString*)passedString1 second:(NSString*)passedString2 {
    if (passedString1 != myString) {
        [myString release];
        myString = [passedString1 retain];
    }
    if (passedString2 != hisString) {
        [hisString release];
        hisString = [passedString2 retain];
    }
}
另外,确保在
dealoc
方法中释放
myString
histring

是的,如果这样做,您的属性(更准确地说,与属性对应的实例变量)将保留传递的字符串。但是,还必须确保在指定新值时释放以前的值。例如:

- (void)setValue:(NSString*)passedString1 second:(NSString*)passedString2 {
    if (passedString1 != myString) {
        [myString release];
        myString = [passedString1 retain];
    }
    if (passedString2 != hisString) {
        [hisString release];
        hisString = [passedString2 retain];
    }
}

另外,请确保在
dealloc
方法中释放
myString
histring

如果要保留任何属性,建议将该属性声明为retain并使用self。上面的代码很容易泄漏内存,因为您在一个方法中保留了一些内容,并且可能在其他地方释放它们。这会造成很多麻烦,因为这两种方法相互关联,但并不基于应用程序逻辑。(吓人!!你必须在以后阅读代码时记住它。如果你想让其他人看你的代码,请将它记录下来…)

当我希望保留某个变量,但仍然不想在标题中使用retain属性时,我会创建一个扩展并覆盖该属性,然后使用self

MyClass.h

@interface MyClass : NSObject
{
    SomeClass *someObject; //Example
    ...
}
@property (nonatomic) SomeClass *someObject;
...
@end
我的班级

@interface MyClass () //Category
@property (nonatomic, retain) SomeClass *someObject;
@end

@implementation MyClass
...
// Use self.someObject and the object will be retained.
// Release that object in dealloc.
@end

编辑:NSString与您的案例相同。只需将
retain
替换为
copy
,因为它推荐用于NSString。

如果您希望保留任何属性,建议将该属性声明为retain并使用self。上面的代码很容易泄漏内存,因为您在一个方法中保留了一些内容,并且可能在其他地方释放它们。这会造成很多麻烦,因为这两种方法相互关联,但并不基于应用程序逻辑。(吓人!!你必须在以后阅读代码时记住它。如果你想让其他人看你的代码,请将它记录下来…)

当我希望保留某个变量,但仍然不想在标题中使用retain属性时,我会创建一个扩展并覆盖该属性,然后使用self

MyClass.h

@interface MyClass : NSObject
{
    SomeClass *someObject; //Example
    ...
}
@property (nonatomic) SomeClass *someObject;
...
@end
我的班级

@interface MyClass () //Category
@property (nonatomic, retain) SomeClass *someObject;
@end

@implementation MyClass
...
// Use self.someObject and the object will be retained.
// Release that object in dealloc.
@end

编辑:NSString与您的案例相同。只需将
retain
替换为
copy
,因为它推荐用于NSString。

您尝试过构建和分析吗?是的,我在这里发现了一些漏洞。我认为这些泄漏是由于passedString1和passedString2被保留而产生的。这些字符串既不是由alloc、copy创建的,也不是由retain创建的,而是在上面的方法中保留的。您是否仅将属性声明为readonly或copy或retain?我已将属性声明为retain。您是否尝试过生成和分析?是的,我在这里发现了一些漏洞。我认为这些泄漏是由于passedString1和passedString2被保留而产生的。这些字符串不是由alloc创建的,copy nor by retain,但已在上述方法中保留。您是否仅将属性声明为readonly或copy or retain?我已将属性声明为retain。如果
myString
恰好与
passedString1
是同一对象,并且当您调用该方法。首先,它将释放myString(使其retain计数为零),然后,您不能保证能够复制
passedString1
,因为它与
myString
相同,并且
myString
可能已被解除分配。如果
myString
恰好与
passedString1
是同一个对象,并且当您调用该方法。首先,它将释放
myString
(使其保留计数为零),然后您不能保证能够复制
passedString1
,因为它与
myString
相同,
myString
可能已经解除分配。新的场景不会改变任何东西。关键是不能依赖于某个数组被保留在其他地方。如果你想拥有所有权,就拥有它。不要指望其他任何东西能保留它。如果该模块稍后被更改怎么办?如果您没有取得所有权,此代码将中断。新方案不会改变任何内容。关键是不能依赖于某个数组被保留在其他地方。如果你想拥有所有权,就拥有它。不要指望其他任何东西能保留它。如果该模块稍后被更改怎么办?如果您没有取得所有权,此代码将被破坏。