繁体   English   中英

iPhone,将对象传递给方法,内存管理

[英]iPhone, passing object to method(s), memory management

我知道已经有很多关于此主题的问题,但是对我来说还不清楚。 所以,我仍然想知道的是,如果我调用一个方法并将其传递给一个对象,那么我是否必须将该对象保留在我的方法中才能在其中使用它。 如果我保留它,该在哪里释放它。 让我们举一个更复杂的例子。 有人可以解释这是怎么回事:

NSString *myStr = [[NSString alloc]initWithString:@"Hello"];

myStr = [self modString2:[self modString1:myStr]];
[myStr release];

//These are the methods...

-(NSMutableString*)modString1:(NSString*)str{
 return [[[str stringByAppendingString:@" Mr. Memory"] mutableCopy] autorelease];
}

-(NSMutableString*)modString2:(NSString*)str{
 return [[[str stringByAppendingString:@" How about this?"] mutableCopy] autorelease];
}

这让我感到困惑。 假设我在方法内部创建一个对象:

[self modString:[self createString]];


-(NSString*)createString{
 NSString *string = [NSString stringWithString:@"Hello"];
 return string;
}

-(NSMutableString*)modString:(NSString *)str{
 [str retain];
 NSMutableString *mut = [NSMutableString stringWithString:str];
 return mut;
}

这是正确的吗? 另一件事:如果我将数组中的字符串复制到类似以下的字符串中:

NSString *str = [NSString alloc[ initWithString:[[arr objectAtIndex:0]copy]]];

保留整个数组,还是这里发生了什么? 那是否意味着我必须释放阵列? 我不懂。 除了苹果之外,还有其他实用资源吗? 我真的很想了解这个...

方法不拥有作为参数传递给它的对象? 对? 而且,如果对象本身是通过以下方法自动释放的方法(之前称为)所返回的对象,则该对象本身就是方法中的对象:return [object autorelease],因此是在方法内部创建的,即首先打电话。

还有一个:

例如,如果我执行以下操作:

request = [[NSMutableURLRequest alloc] initWithURL:url];

我可以在此之后释放该URL,还是仍然必须保留该网址才能使请求有效?

如果只在方法内部需要它,则不需要保留它。
如果需要将其存储在实例变量中以备后用,请保留它,并在dealloc方法中释放它,或者在为实例变量分配新对象时将其释放。

有关我的评论的示例

如果您修改字符串(NSMutableString)的值,则不必担心。 您只需要在创建字符串的方法中将其释放。 如果您返回指向另一个字符串的指针,并且将此新字符串分配给前一个字符串,则可能会遇到问题。 在这种情况下,您将无法再访问原始指针,并且由于无法释放而导致内存泄漏

例1

{
    NSArray * arr = [ [ NSArray alloc ] initWithObject: @"Foo", @"Bar", nil ];
    [ self someMethod: arr ];
    [ arr release ];
}
- ( void )someMethod: NSArray * arr
{
    arr = [ NSArray emptyArray ];
}

没关系,即使您在someMethod分配了另一个数组,也不会发生内存泄漏,因为指针是该方法的局部指针,并且不会影响原始指针。

例2

{
    NSArray * arr = [ [ NSArray alloc ] initWithObject: @"Foo", @"Bar", nil ];
    [ self someMethod: &arr ];
}
- ( void )someMethod: NSArray ** arr
{
    *( arr ) = [ NSArray emptyArray ];
}

在这里,我们在修改原始指针时发生了内存泄漏。 注意我们使用了**,这意味着我们有一个指向指针的指针。

例3

{
    NSArray * arr = [ [ NSArray alloc ] initWithObject: @"Foo", @"Bar", nil ];
    arr           = [ self someMethod: arr ];
}
- ( NSArray * )someMethod: NSArray * arr
{
    return [ NSArray emptyArray ];
}

内存泄漏,因为我们已经重新定义了指向arr数组的指针。 它已被分配,但由于指针指向另一个变量,所以我们无法释放它。

在您的第一段代码中,您永远不会真正修改字符串myStr的值,只是将方法返回的值扔掉了。 如果将行修改为如下所示:

    NSString *myStr2 = [self modString1:[self modString2:myStr]];

字符串myStr2的值为“你好,这是什么?先生。内存”,它将是一个自动释放的对象,您不必释放它。

另外,请记住,将对象添加到可变数组时,该对象会自动保留,以便在将其添加到数组后可以释放它,并且该对象将保持活动状态,直到从数组中删除该对象为止。阵列被释放。

我将尝试解释指针,如果您已经知道这一点,对不起。

大多数objc对象都是指针。 您可以知道,因为它们在对象名称的末尾带有*。 NSString不是指针,但是NSString *是指针。

NSString指针(NSString *)对象仅包含该字符串存储在内存中的空间的地址。 创建指针对象时,需要向计算机询问用于存储对象的空间。 在objc中,您可以通过调用静态alloc方法来做到这一点。 所以

NSString* s = nil; //s contains NOTHING
s = [[NSString alloc] stringWithString:@"hello"]; //space in memory is created for s, s contains the address to that memory. That memory block now holds "hello".

现在,您的计算机希望您告诉它是否不再使用该内存块。 那是你打电话的时候

[s release];

让您的计算机知道它可以接管该内存块(我想您知道objc可以使用的计数器样式的内存管理)。 如果您尝试访问该存储块之后不再是您的存储块,那么当您遇到所有这些有趣的存储错误时,就可以了。

现在,当您调用需要传递诸如以下内容的对象的方法时

[foo doSomethingWith:s];

您实际传递的不是对象“ hello”,而是将指针传递到保存“ hello”的内存中的地址。 当您具有庞大的数据结构(例如大小为1,000,000的整数数组)时,这种处理方式会派上用场。 无需将庞大的数组传递给函数,只需传递该数组的指针即可。 这样更快,更高效。

那么什么时候应该释放分配的对象呢? 通常, 当您不再需要它们时 ,而是在分配它们的相同功能中,就希望释放它们。 如果它们是实例变量,则可以在类的init函数中进行分配,并在dealloc函数中进行释放。 在许多情况下,您不需要保留/复制内容 ,因此,除非您遇到内存错误,否则我不会担心。

希望这对XD有帮助。如果objc的信息不正确,对不起。 我通过C ++学习了内存管理,这是完全不同的。

另一段代码:我仍然对它不满意:

假设这是功能的一部分。

NSArray *txtArray = [[NSArray alloc]init];

if(aTxtField.text != NULL){ NSString *aTxtFieldTxt = [[NSString alloc]initWithString:aTxtField.text]; aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; [aTxt appendString:waotwTxtFieldTxt]; [aTxtFieldTxt release]; txtArray = [aTxt componentsSeparatedByString:@" "]; aTxt = [[txtArray objectAtIndex:0] mutableCopy]; for(int i = 1; i < [txtArray count]; i++){
[aTxt appendString:@"+"]; [aTxt appendString:[[txtArray objectAtIndex:i]copy]]; } [txtArray release]; return aTxt; }

if(aTxtField.text != NULL){ NSString *aTxtFieldTxt = [[NSString alloc]initWithString:aTxtField.text]; aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; [aTxt appendString:waotwTxtFieldTxt]; [aTxtFieldTxt release]; txtArray = [aTxt componentsSeparatedByString:@" "]; aTxt = [[txtArray objectAtIndex:0] mutableCopy]; for(int i = 1; i < [txtArray count]; i++){
[aTxt appendString:@"+"]; [aTxt appendString:[[txtArray objectAtIndex:i]copy]]; } [txtArray release]; return aTxt; }

if(aTxtField.text != NULL){ NSString *aTxtFieldTxt = [[NSString alloc]initWithString:aTxtField.text]; aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; [aTxt appendString:waotwTxtFieldTxt]; [aTxtFieldTxt release]; txtArray = [aTxt componentsSeparatedByString:@" "]; aTxt = [[txtArray objectAtIndex:0] mutableCopy]; for(int i = 1; i < [txtArray count]; i++){
[aTxt appendString:@"+"]; [aTxt appendString:[[txtArray objectAtIndex:i]copy]]; } [txtArray release]; return aTxt; }

if(aTxtField.text != NULL){ NSString *aTxtFieldTxt = [[NSString alloc]initWithString:aTxtField.text]; aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; [aTxt appendString:waotwTxtFieldTxt]; [aTxtFieldTxt release]; txtArray = [aTxt componentsSeparatedByString:@" "]; aTxt = [[txtArray objectAtIndex:0] mutableCopy]; for(int i = 1; i < [txtArray count]; i++){
[aTxt appendString:@"+"]; [aTxt appendString:[[txtArray objectAtIndex:i]copy]]; } [txtArray release]; return aTxt; }

if(aTxtField.text != NULL){ NSString *aTxtFieldTxt = [[NSString alloc]initWithString:aTxtField.text]; aTxtFieldTxt = [aTxtFieldTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; [aTxt appendString:waotwTxtFieldTxt]; [aTxtFieldTxt release]; txtArray = [aTxt componentsSeparatedByString:@" "]; aTxt = [[txtArray objectAtIndex:0] mutableCopy]; for(int i = 1; i < [txtArray count]; i++){
[aTxt appendString:@"+"]; [aTxt appendString:[[txtArray objectAtIndex:i]copy]]; } [txtArray release]; return aTxt; }

这样可以吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM