2

我的应用程序从 Internet 下载视频并将其保存在 iPhone 中。

我正在使用此代码

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];

[request setHTTPMethod:@"GET"];
NSError *error;
NSURLResponse *response;


NSString *documentFolderPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *videosFolderPath = [documentFolderPath stringByAppendingPathComponent:@"videos"]; 

//Check if the videos folder already exists, if not, create it!!!
BOOL isDir;
if (([fileManager fileExistsAtPath:videosFolderPath isDirectory:&isDir] && isDir) == FALSE) {
    [[NSFileManager defaultManager] createDirectoryAtPath:videosFolderPath withIntermediateDirectories:YES attributes:nil error:nil];
}

NSString *filePath = [videosFolderPath stringByAppendingPathComponent:@"name.mp4"];

if ([fileManager fileExistsAtPath:filePath ] == YES) {
    NSLog (@"File exists");
}
else {
    NSLog (@"File not found");
    NSData *urlData;
    NSString *downloadPath = @"http://www.mywebsite.com/name.mp4";
    [request setURL:[NSURL URLWithString:downloadPath]];
    urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    BOOL written = [urlData writeToFile:filePath atomically:NO];
    if (written)
        NSLog(@"Saved to file: %@", filePath);
    else {NSLog(@"problem");}
}

一切正常,但我想添加一个进度视图,以指示下载状态。

问题(我认为但我不确定)是我的 NSURLConnection 本身并没有作为委托,所以像这样的方法

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

或者

-(void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite{

永远不会被调用。

我试着用

urlData = [[NSURLConnection alloc] initWithRequest:request delegate:self];

但是当我尝试写入文件时应用程序崩溃

[urlData writeToFile:filePath atomically:NO];

我能做些什么?谢谢

4

2 回答 2

5

您正在做的是发送“同步”请求,这意味着正在下载 HTTP 响应的线程将挂起,直到获取所有数据。在 UI 线程上执行此操作绝不是好事,即使您不想显示任何下载进度指示器。我建议使用 NSURLConnection 类,设置它的委托,并响应委托方法。可以在http://snippets.aktagon.com/snippets/350-How-to-make-asynchronous-HTTP-requests-with-NSURLConnection找到一个小教程。

一旦您成为连接的委托人,您就可以在连接收到响应时获取内容长度:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response;   
    contentSize = [httpResponse expectedContentLength];
}

然后,要计算新数据到达时的下载总进度,请执行以下操作:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // download data is our global NSMutableData object that contains the
    // fetched HTTP data.
    [downloadData appendData:data];
    float progress = (float)[downloadData length] / (float)contentSize;
    [progressView setValue:progress];
}

更新:

关于如何使用 Foundation 进行异步 HTTP 的另一个示例:http: //codewithchris.com/tutorial-how-to-use-ios-nsurlconnection-by-example/

于 2011-07-21T18:40:04.070 回答
1

您在这里使用同步请求。

该文件说 - 同步加载建立在类提供的异步加载代码之上。当异步加载系统在专门为此加载请求生成的线程上执行 URL 加载时,调用线程被阻塞。为了执行同步加载,调用线程中不需要特殊的线程或运行循环配置。

请参阅此处的类参考

阅读类参考后,您可以发送异步请求或初始化请求、设置委托并启动。

于 2011-07-21T17:23:19.680 回答