0

私のアプリは、NSURLConnection を使用してインターネットからファイルをダウンロードしています。

2 つの問題が発生しています。

1) [connection didReceiveData] が呼び出されることはありません

2) [接続 didFinishDownloading] が呼び出されると、自分の self.currentData が空になります

私は何を間違っていますか?

私のヘッダーは次のようになります。

@interface DIFileDownloader : NSObject <NSURLConnectionDelegate> {

    NSMutableData *currentData;

}

@property (nonatomic, assign) id <DIFileDownloaderDelegate> delegate;

@property (nonatomic, retain) NSMutableArray *supportedFormats;

@property (nonatomic, retain) NSMutableData *currentData;

@property (nonatomic, retain) NSURLConnection *downloadAgent;

@property (nonatomic) long long expectedContentSize;

@property (nonatomic) float currentDownloadProgress;

@property (nonatomic, getter = isRunning) BOOL running;

-(instancetype)initWithSupportedFormats:(NSArray *)extensions;

-(void)downloadFileAtURL:(NSURL *)url;

-(NSString *)documentsDirectoryPath;

@end

そして私の実装ファイル:

-(instancetype)initWithSupportedFormats:(NSArray *)extensions {

    self.supportedFormats = [[NSMutableArray alloc] initWithArray:extensions];

    self.running = NO;
}

-(void)downloadFileAtURL:(NSURL *)url {

    NSString *fileExtension = [url pathExtension];

    if ([self.supportedFormats containsObject:fileExtension]) {

        self.downloadAgent = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:url] delegate:self];

        [self.downloadAgent start];

        NSLog(@"Beginning download at URL:%@", url.absoluteString);

    }
    else {

    }

}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    NSLog(@"Connection recieved response with size: %f", (float)[response expectedContentLength]);

    self.expectedContentSize = (float)[response expectedContentLength];

    self.running = YES;

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;

    NSLog(@"%i", [httpResponse statusCode]);

    /*

    if ([httpResponse statusCode] >= 200 && [httpResponse statusCode] <= 299) {

    }

     */

}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    NSLog(@"%f", (float)[data length]);

    [currentData appendData:data];

    self.currentDownloadProgress = ((float)[data length] / self.currentDownloadProgress);

    NSLog(@"Connection recieved data. New progress is: %f", self.currentDownloadProgress);

    if ([self.delegate respondsToSelector:@selector(downloader:progressChanged:)]) {
        [self.delegate downloader:self progressChanged:self.currentDownloadProgress];
    }

}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

    NSLog(@"Connection failed");

    if ([self.delegate respondsToSelector:@selector(downloader:failedToDownloadFileAtURL:reason:)]) {
        [self.delegate downloader:self failedToDownloadFileAtURL:connection.originalRequest.URL reason:error];
    }

}

-(void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL {

    NSLog(@"Connection finished downloading with size: %f", (float)[currentData length]);

    self.running = NO;

    NSString *filename = [destinationURL.absoluteString lastPathComponent];

    NSString *docPath = [self documentsDirectoryPath];

    NSString *pathToDownloadTo = [NSString stringWithFormat:@"%@/%@", docPath, filename];

    NSError *error = nil;

    [currentData writeToFile:pathToDownloadTo options:NSDataWritingAtomic error:&error];

    if (error != nil) {

        NSLog(@"DIFileDownloader: Failed to save the file because: %@", [error description]);

        if ([self.delegate respondsToSelector:@selector(downloader:failedToDownloadFileAtURL:reason:)]) {
            [self.delegate downloader:self failedToDownloadFileAtURL:connection.originalRequest.URL reason:error];
        }

} 
    else {

        if ([self.delegate respondsToSelector:@selector(downloader:finishedDownloadingFileNamed:atPath:)]) {
            [self.delegate downloader:self finishedDownloadingFileNamed:filename atPath:pathToDownloadTo];
        }

    }

}

- (NSString *)documentsDirectoryPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectoryPath = [paths objectAtIndex:0];
    return documentsDirectoryPath;
}

@end
4

1 に答える 1

0

他の人や私のコメントで述べたように、コードには修正が必要なバグがいくつかあります。

しかし、大きな誤解も 1 つありますNSURLConnection

connectionDidFinishDownloading:destinationURL:つまり、 NSURLConnection の2つのデリゲートのデリゲートメソッドではなく、ケースで実装することになっていますNSURLConnectionDelegateNSURLConnectionDataDelegate

実装する必要があるデリゲート メソッドの最小限のセットは次のとおりです。

の場合NSURLConnectionDelegate:

  • (void) 接続: (NSURLConnection *) 接続 didFailWithError: (NSError *) エラー;

次にNSURLConnectionDataDelegate

  • (void)接続:(NSURLConnection *)接続didReceiveResponse:(NSURLResponse *)応答;

  • (void)接続:(NSURLConnection *)接続didReceiveData:(NSData *)データ;

  • (void)connectionDidFinishLoading:(NSURLConnection*)接続;

よろしければ、最小限の実装のサンプルを Gist に掲載しました: SimpleGetHTTPRequestを使用すると、独自の HTTP 要求クラスを実装するためのジャンプ スタートが得られます。

于 2013-07-14T08:00:31.637 に答える