簡體   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