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