0

UITableViewがあり、セルを選択すると、サービス呼び出しを行って、WebサービスからPDFファイルを非同期でダウンロードします。複数のセルを次々に(個別に)選択するまでは、うまく機能します。その後、物事は南に進み始めます。

明確にするために、いくつかの(簡略化された)コードを次に示します。

MasterViewController.mの内部:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //To uniquely identify this field, I build a simple string using the indexPath.
    NSString *key = [[NSString alloc]initWithFormat:@"%d.%d",pIndex.section,pIndex.row];

    //Use a pre-populated NSDictionary to specify the file I want from the server.
    NSString *reportID = [reportDictionary valueForKey:key];

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/RequestReportWithID",myConnectionObject.ServiceURL]];

    NSMutableDictionary *body = [[NSMutableDictionary alloc] initWithObjectsAndKeys:reportID, @"reportID", nil];

    NSData *requestData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody: requestData];

    //Create a new object as delegate to receive the data, also add the key to assist with identification.
    ReportDownloader *newReportDownloader = [[ReportDownloader alloc]initWithDelegate:self andKey:key];

    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:newReportDownloader];
    if (connection)
    {
        //Nothing to do here, request was made.
    }
}

ReportDownloader.mの内部:

long long expectedReportSize;
NSString *key;
NSData *thisReport;

-(NSObject*)initWithDelegate:(NSObject*)pDelegate andKey:(NSString*)pKey
{
    myTypedDelegate = (MasterViewController*)pDelegate;
    Key = pKey;
    return self;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    expectedReportSize = [response expectedContentLength];
    NSLog(@"Key:%@, Expected Size=%lld bytes",Key, [response expectedContentLength]);
    thisReport = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{
    [thisReport appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{
    //Here is where things go wrong...
    NSLog(@"Key:%@, Actual Size=%ld bytes",Key, (unsigned long)[thisReport length]);
}

上記のコードは、単一のレポートで正常に機能します。また、高速回線では、3〜4のレポートで正常に機能しますが、それ以上のことを実行しようとすると、予想される長さが実際の長さと一致しなくなります。そして、なぜyyyyが理解できません...。

上記のコードによって生成された出力を参照してください: (indexPath1.1のレポートのみが正しくダウンロードされたことに注意してください)

Key:1.0, Expected Size=304006 bytes
Key:1.3, Expected Size=124922 bytes
Key:1.0,   Actual Size=369494 bytes
Key:1.3,   Actual Size=380030 bytes
Key:1.2, Expected Size=179840 bytes
Key:1.4, Expected Size=377046 bytes
Key:1.2,   Actual Size=114376 bytes
Key:1.5, Expected Size=175633 bytes
Key:1.4,   Actual Size=180558 bytes
Key:1.5,   Actual Size=274549 bytes
Key:1.1, Expected Size=443135 bytes
Key:1.1,   Actual Size=443135 bytes

PDFドキュメントを開こうとすると、データの破損が確認されます。これは、データサイズがexpectedContentLengthと一致しなかったすべてのファイルで失敗します。

私はこの振る舞いに完全に困惑しています。私が明らかにn00bの間違いを犯していて、ここの誰かがそれを見つけてくれることを望んでいます。

ReportDownloaderクラスを作成した主な理由は、このような問題を回避するためでした。

私のコードをスキャンするのに時間を割いてくれた人に事前に感謝します!

4

1 に答える 1

0

わかりました、この問題の解決策はここにあります: https ://stackoverflow.com/a/1938395/1014983 James Waldによるこの回答は、質問の受け入れられた回答ではありませんが、複数の同時非同期NSURLConnectionsに関する私のすべての問題を完全に解決しました。

実装についてサポートが必要な場合はお知らせください。ただし、非常に簡単です。

于 2013-04-11T08:32:23.553 に答える