0

すべてのネットワーク通信に ASIHttpRequest を使用するプロジェクトを継承しました。私たちが使用している特定のバージョンについては不明です。私が言えることは、.h ファイルから、特定のファイルの最も古い作成日が 17/08/10 (ASIDataDecompressor) であるということだけです。

完了ブロックと失敗ブロックを使用しています。何らかの理由で、サーバーが応答しない場合にのみ実際に発生するはずの障害ブロックが頻繁にトリガーされます。私たちのログは正常に見え、エラーが発生した頃にサーバーに問題があったという通知 (Airbrake) を受け取っていないので、今のところ、私たちのサーバーは問題なく、それはアプリであるという前提で先に進んでいます犯人。

Instruments (Leaks) を介してアプリを実行することにしましたが、リクエストを強制的に失敗させると、すぐに最大 27 個のリークが作成されることに驚きました。私はインストゥルメントをうまく使いこなす方法がわからないので、情報を手に入れた今、その情報をどうしたらよいかよくわかりません。

コードを投稿して、目立ったものがないかどうかを確認したいと思いました。

viewDidLoad では、このコードが実行されます

[[MyAPI sharedAPI] getAllHighlights:pageNumber:perPage onSuccess:^(NSString *receivedString,NSString *responseCode) {
        [self getResults:receivedString];
        if(![responseCode isEqualToString:@"Success"]) {
            [self hideProgressView];
            appDelegate.isDiscover_RefreshTime=YES;                
            [[MyAPI sharedAPI] showAlert:responseCode]; 
        } else {
            NSString *strLogEvent=@"Discover_Highlights_Loaded Page_";
            strLogEvent=[strLogEvent stringByAppendingFormat:@"%i",intPageNumber];
            [FlurryAnalytics logEvent:strLogEvent timed:YES];
        }
    } onFail:^(ASIFormDataRequest *request) {
        NSDictionary *parameters = [[MyAPI sharedAPI] prepareFailedRequestData:request file:@"Discover" method:_cmd];
        [FlurryAnalytics logEvent:@"Unable_to_Connect_to_Server" withParameters:parameters  timed:true];
        [self hideProgressView];
        appDelegate.isDiscover_RefreshTime=YES;

        [[AfarAPI sharedAPI] showAlert:@"Unable to Connect to Server."];
        [tblHighlightsGrid reloadData];
        [tblListHighlights reloadData];

}];

これらの typedef は、API Singleton の上部で定義されています。

typedef void (^ASIBasicBlockWrapper)(NSString *responseString,NSString *responseCode);
typedef void (^ASIBasicBlockWrapperFail)(ASIFormDataRequest *request);

MyAPISingleton#getAllHighlights...

- (void)getAllHighlights:(NSString *)pageNumber:(NSString *)perPage onSuccess:(ASIBasicBlockWrapper)cb1 onFail:(ASIBasicBlockWrapperFail)cb2{
    NSString *access_token= [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"];

    NSString *url = [baseURL stringByAppendingFormat:AFAR_GET_ALL_HIGHLIGHTS_ENDPOINT, pageNumber,perPage];
    if (access_token) { url = [url stringByAppendingFormat:ACCESS_TOKEN, access_token]; }

    __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:url]];
    [request setRequestMethod:@"GET"];
    [request setDelegate:self];  
    [self executeAsynchronousRequest:request onSuccess:cb1 onFail:cb2];
}

最後に、MyAPI#executeAsynchronousRequest:

- (void) executeAsynchronousRequest:(ASIFormDataRequest *)request onSuccess:(ASIBasicBlockWrapper)cb1 onFail:(ASIBasicBlockWrapperFail)cb2
{
    [request setCompletionBlock:^{
        int statusCode = [request responseStatusCode];
        NSString *statusMessage = [self statusErrorMessage:statusCode];
        cb1([request responseString],statusMessage);
    }];
    [request setFailedBlock:^{
        cb2(request);
    }];

    [request startAsynchronous];    
}

27 のリークが作成された理由について、何か目立ったものはありますか?

4

1 に答える 1

0

私はこれを理解しました。

ASIHttpRequestドキュメントは、リクエスト オブジェクトを __block ストレージ メカニズムで指定する必要があるという事実について非常に明確です。

リクエストを宣言するときの __block 修飾子の使用に注意してください。これは重要です! リクエストは常にブロックを保持するため、リクエストを保持しないようにブロックに指示します。これは、保持サイクルを防ぐために重要です。

getAllHighlights() ではそれを行っていますが、別のメソッド (executeAsyncRequest) に引数としてリクエスト オブジェクトを送信しています。__block ストレージ タイプはローカル変数でのみ宣言できるため、メソッド シグネチャでrequestは、通常の ASIFormDataRequest に型指定されているだけで、__block ステータスを失っているように見えます。

秘訣は、ブロックで使用する前に引数をキャストすることです (それが技術的に正確かどうかはわかりません)。

executeAsyncRequest の漏れのない実装を次に示します。

- (void) executeAsyncRequest:(ASIFormDataRequest *)request onSuccess:(ASIBasicBlockWrapper)cb1 onFail:(ASIBasicBlockWrapperFail)cb2
{
    // this is the important part. now we just need to make sure
    // to use blockSafeRequest _inside_ our blocks
    __block ASIFormDataRequest *blockSafeRequest = request;

    [request setCompletionBlock: ^{
        int statusCode = [blockSafeRequest responseStatusCode];
        NSString *statusMessage = [self statusErrorMessage:statusCode];
        cb1([blockSafeRequest responseString],statusMessage);
    }];

    [request setFailedBlock: ^{
        cb2(blockSafeRequest);
    }];

    [request startAsynchronous];    
}
于 2012-04-24T01:32:18.600 に答える