0

このコードでエラーを見つけることができません:

-(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 に送信されたメッセージ

リクエスト データを保持し、メモリ リークを防ぐ方法がわかりません。

4

2 に答える 2

3

私はこの図書館について何も知らないので、バイキングのアドバイスに耳を傾けるべきでしょう。

ただし、ブロックとリクエスト オブジェクトの間に作成された保持サイクルの結果であるリークについてはお手伝いできます。request具体的には、オブジェクトが ( 経由で) コード ブロック オブジェクトへの強い参照を保持していることに注意してくださいrequest.completionBlock

request次に、コード ブロック オブジェクトはにアクセスするため、 への強い参照を保持していrequest.responseDataます。_selfさらに、あなたのコードは ARC である可能性が最も高いように見えますが、それは非 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];
}

現在、完了ブロックは応答オブジェクトへの弱い参照を保持しているため、保持サイクルが壊れています。一般に、弱い参照へのローカルな強い参照を作成して、オブジェクトがそのジョブを実行するのに十分な時間存在するようにする必要があることに注意してください。ただし、この特定のケースでは、必要ないようです。nil 画像でも問題ないと思います。

于 2012-08-22T19:36:15.670 に答える
1

ドキュメントから

- (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


ASIHTTPRequestの元の作成者は、もうサポートしていないことに注意してください。彼は自分の理由を非常によく説明し、代替プロジェクトへのリンクと提案を提供します。優れたブロックベースのインターフェースを持つAFNetworkingに満足しています。

于 2012-08-22T18:41:15.703 に答える