0

我無法找到錯誤在此代碼:ASIHTTPRequest塊內存泄露

-(void)downloadImageFromURL:(NSURL*)url withCompletionBlock:(RSSMessageImageDownloadCompletionBlock)completionBlock 
{ 

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 

    __block RSSMessage *_self = self; 
    request.completionBlock = 
    ^{  
     __block NSData *responseData = request.responseData; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      _self.image = responseData;    
      [[[UIApplication sharedApplication] delegate] saveContext]; 
      if(completionBlock != nil) 
      { 
       completionBlock(); 
      } 

     }); 
    }; 

    [request startAsynchronous]; 
} 

在這種形式下,我得到了來自儀器內存泄漏。我假設這是因爲我之前缺少__block關鍵字:ASIHTTPRequest * request = [ASIHTTPRequest requestWithURL:url];

但是,當我把這個添加關鍵字上述行我有錯誤,如:

* - [NSConcreteMutableData isNSData__]:消息發送到釋放實例0xdeab380

我不知道如何保留請求數據而不會泄漏內存。

回答

1

from the docs

- (IBAction)grabURLInBackground:(id)sender 
{ 
    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; 
    __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 
    [request setCompletionBlock:^{ 
     // Use when fetching text data 
     NSString *responseString = [request responseString]; 

     // Use when fetching binary data 
     NSData *responseData = [request responseData]; 
    }]; 
    [request setFailedBlock:^{ 
     NSError *error = [request error]; 
    }]; 
    [request startAsynchronous]; 
} 

好像本身需要被打上__block


注意請求,即original author of ASIHTTPRequest isnt supporting it anymore。他很好地解釋了他的理由,並提供了替代項目的鏈接和建議。我很滿意AFNetworking,它有一個很好的基於塊的界面。

+0

我檢查了__block關鍵字,並且在我的問題中提到了另一個問題(第二部分)。無論我現在得出結論,在dispatch_get_main_queue()中做任何事情都會導致內存泄漏。所以部分是真的,它缺少關鍵字,我會接受你的答案。 – Ertai

+0

如果在ARC下編譯,該示例具有保留週期。 –

3

我對這個圖書館一無所知,所以你應該留意維京人的建議。

但是,我可以幫助你處理你的泄漏,這是在塊和請求對象之間創建的保留週期的結果。具體而言,請注意,您的request對象持有對代碼塊對象的強烈引用(通過request.completionBlock)。

反過來,您的代碼塊對象持有對request的強烈參考,因爲它訪問request.responseData。此外,請注意,您的代碼看起來很可能是ARC,但這並不能解釋您的_self變量構造,它看起來像非ARC弱引用。非ARC __block不保留該對象。在ARC下,__block確實會導致保留。

假設ARC,我會建議進行以下更改。

-(void)downloadImageFromURL:(NSURL*)url withCompletionBlock (RSSMessageImageDownloadCompletionBlock)completionBlock 
{ 
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 

    __weak ASIHTTPRequest *weakRequest = request; 
    __weak RSSMessage *weakSelf = self; 

    request.completionBlock = ^{ 
     NSData *responseData = weakRequest.responseData; 
     // Check for nil if not ok with nil data 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      weakSelf.image = responseData;    
      [[[UIApplication sharedApplication] delegate] saveContext]; 
      if(completionBlock != nil) 
      { 
       completionBlock(); 
      } 
     }); 
    }; 
    [request startAsynchronous]; 
} 

現在,完成塊包含對響應對象的弱引用,該引用會中斷保留週期。請注意,一般來說,您應該爲弱參考創建一個本地強引用,以確保該對象保持足夠長的時間以完成其工作。但是,在這種特殊情況下,似乎並不需要。我認爲可以有一個零圖像。