[英]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.