2010-04-16 71 views
0

作爲一個免責聲明,我想說我對Objective-C和Cocoa相當陌生。目前我正在嘗試編寫一個可以將XML數據發佈到特定端點的基本應用程序。爲此,我創建了一個ServiceRouter類,它使用NSURLConnection將XML數據發佈到特定的URL。NSURLConnection泄漏問題

ServiceRouter類旨在用作包含特定於Web服務的XML查詢的子類的基礎。在下面的例子中,我將ServiceRouter的子類創建爲一個ServiceImplementation類。

當它的時間來產生併發布了XML,我創建了ServiceImplementation類的一個實例,像這樣:

[[ServiceImplementation alloc] createServiceSpecificXML]; 

這一切似乎很好地工作。問題是泄漏報告了一些問題。相當缺乏經驗,我不確定從哪裏開始。大多數情況下,NSURLConnection代碼是從Apple的文檔中提取的。

遵循基本的內存管理規則,我想我必須在某個時候釋放我的ServiceImplementation實例。我感到困惑的是,鑑於NSURLConnection的異步特性,這應該如何處理。這是autorelease的候選人嗎?

我希望有更多Objective-C/Cocoa經驗的人可以看看事情並告訴我我是否正朝着正確的方向前進。

這裏的ServiceRouter類:

@interface ServiceRouter : NSObject { 
    NSMutableData *receivedData; 
} 

-(void)postXMLToURL:(NSString *)url xml:(NSString *)xmlData; 
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; 
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 
-(void)connectionDidFinishingLoading:(NSURLConnection *)connection; 
@end 

@implementation ServiceRouter 

- (void)postXMLToURL:(NSString *)url xml:(NSString *)xmlData 
{ 
    NSLog(@"Posting XML to URL: %@", url); 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]]; 
    [request setHTTPMethod:@"POST"]; 
    [request setValue:@"application/xml" forHTTPHeaderField:@"Content-type"]; 
    [request setValue:@"application/xml" forHTTPHeaderField:@"Accept"]; 

    [request setValue:[NSString stringWithFormat:@"%d", [xmlData length]] forHTTPHeaderField:@"Content-length"]; 
    [request setHTTPBody:[xmlData dataUsingEncoding: NSUTF8StringEncoding]]; 

    NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; 
    if(connection) { 
     NSLog(@"Connection created"); 
     receivedData = [[NSMutableData data] retain]; 
    } else { 
     NSLog(@"Issue with connection!"); 
    } 
} 

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    if([response respondsToSelector:@selector(statusCode)]) 
    { 
     int statusCode = [((NSHTTPURLResponse *)response) statusCode]; 
     NSLog(@"HTTP Response code: %i", statusCode); 
    } 
    NSLog(@"Received response"); 
    [receivedData setLength:0]; 
} 

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    NSLog(@"Received data: %@", data); 
    [receivedData appendData:data]; 
} 

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    [connection release]; 
    [receivedData release]; 

    NSLog(@"Connection failed! Error - %@", [error localizedDescription]); 
} 

-(void)connectionDidFinishingLoading:(NSURLConnection *)connection 
{ 
    NSLog(@"Succeeded! Received %d bytes of data", [receivedData length]); 

    [connection release]; 
    [receivedData release]; 
} 
@end 

這裏是我的ServiceImplementation類:

@interface ServiceImplementation : ServiceRouter { 
} 
-(void) createServiceSpecificXML; 
@end 

@implementation ServiceImplementation 

-(void) createServiceSpecificXML 
{ 
    NSString *xmlData = @"<example><ignore/></example>"; 
    [super postXMLToURL:@"http://site.com/endpoint.xml" xml:xmlData]; 
} 

@end 

回答

1

你永遠不會初始化實例。僅僅分配是不夠的。您必須致電init或其他一些初始化程序 - 最好與alloc在同一行。

從你的(工作但奇數)構造[[NSMutableData data] retain],我猜你還沒有讀過很多蘋果的基本引物。我會推薦至少The Objective-C Programming Languagememory management guide。這兩者都不是很長,在這兩者之間,我想你會澄清很多你的不確定性。

+0

我已閱讀通過您建議的蘋果引物,他們肯定有幫助,謝謝。我已經更新了上面的代碼。因此,泄漏不再報告問題。 作爲參考,我確保ServiceImplementation實例已正確初始化,確保在方法結束時釋放在postXMLToURL中創建的NSMutableURLRequest,並確保我的NSURLConnection已被自動釋放。 也許我能看到的唯一問題是,當前connectionDidFinishingLoading嘗試手動釋放NSURLConnection。這可能與調用autorelease的衝突? – ndg 2010-04-17 15:26:23

+0

應該指出,我目前被迫自動釋放NSURLConnection,因爲根據我的經驗,有些情況下connectionDidFinishLoading永遠不會被調用。當然,autorelease會在connectionDidFinishingLoading和didFailWithError方法中手動釋放NSURLConnection? – ndg 2010-04-17 15:29:01

+0

從內存管理契約的角度來看,autorelease和release是等價的。兩者都放棄了對象的所有權。如果你只擁有一個對象,釋放兩次是錯誤的。但更重要的一點是,autorelease可能不是這裏的正確工具。你不能相信一個自動釋放的對象會繞過當前的循環週期。在你使用它之前,NSMutableData對象可能會從你的下面消失。 – Chuck 2010-04-17 17:24:47