objective-c - NSURLConnection 下载多张图片

标签 objective-c xml cocoa macos nsurlconnection

我正在尝试从 XML 提要中存储的 URL 下载多个图像。从 XML 获取图像 url 工作正常。但是,NSURLConnection 正在创建空文件,但数据已按照 NSLog 中的说明接收。在connectionDidFinishLoading:(NSURLConnection *)connection中,接收到数据和正确的字节,问题是如何使接收到的数据写入正确的文件。

半工作代码:

-(void)parsingComplete:(XMLDataSource*)theParser 
{
    /*  iterate through the Categories and create the 
        sub-directory if it does not exist  
     */
    for (int i = 0; i < [categories count]; i++) {
        NSString *cat      = [NSString stringWithFormat:@"%@/%@",BASE_DIR,[[categories objectAtIndex:i] objectForKey:@"name"]];
        NSString *catName  = [[categories objectAtIndex:i] objectForKey:@"name"];
        NSArray  *catArray = [[categories objectAtIndex:i] objectForKey:@"images"];

        /*  create the sub-direcotry naming it the #category# key  */
        if (![FILEMANAGER fileExistsAtPath:cat]) {
            [FILEMANAGER createDirectoryAtPath:cat withIntermediateDirectories:NO attributes:nil error:nil];
        }

        //NSLog(@"\n\nCategory: %@",cat);
        for (int x = 0; x < [catArray count]; x++) {
            //NSLog(@"Image: %@",[[catArray objectAtIndex:x] objectForKey:@"imageUrl"]);   
            /*  download each file to the corresponding category sub-directory  */
            fileOut = [NSString stringWithFormat:@"%@/%@_0%i.jpg",cat,catName,x];

            NSURLRequest *imageRequest = 
            [NSURLRequest requestWithURL:[NSURL URLWithString:[[catArray objectAtIndex:x] objectForKey:@"imageUrl"]]
                             cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
            NSURLConnection *imageConnection = [[NSURLConnection alloc] initWithRequest:imageRequest delegate:self];

            int counter = 0;
            //BOOL result = NO;
            if(imageConnection)
            {
                NSLog(@"Counter: %i",counter++);
                receivedData = [[NSMutableData data] retain];
                /*result = */[receivedData writeToFile:fileOut atomically:YES];
            }
            /*
                if (!result) NSLog(@"Failed"); else NSLog(@"Successful");
             */
        }
    }
}

#pragma mark NSURLConenction

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response  {  
    [receivedData setLength:0];  
} 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data  {  
    [receivedData appendData:data];
}  
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // release the connection, and the data object
    [connection release];
    // receivedData is declared as a method instance elsewhere
    [receivedData release];
    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection  
{  
    // do something with the data  
    // receivedData is declared as a method instance elsewhere  
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);  
    NSString *aStr = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];  
    // release the connection, and the data object  
    //[receivedData release];  
} 

最佳答案

您必须等到连接告诉您连接已完成,然后才能写入数据。连接在另一个线程上处理;如果您尝试立即在原始线程上访问数据,那么其中将不会有任何内容。

您应该将 writeToFile: 调用移至 connectionDidFinishLoading: 的末尾,或者移至您从此处调用的另一个方法。这是您知道数据已全部收集的第一点。

我还建议在 didRecieveResponse: 中创建 NSMutableData 实例,以便您知道它在正确的时间可用。这将更具可读性/易于理解。您可以将委托(delegate)方法视为一个集体“范围”——数据仅在其中使用,因此应该在其中一个方法内部创建。

回复您的评论:

一种可能性是在后台运行整个 parsingComplete: 方法,因为您在这个下载过程中需要完成很多工作,并且似乎没有触及 GUI线程,并使用 +[NSURLConnection sendSynchronousRequest:returningResponse:error:] 。这样,您的代码将只等待数据完整地返回,并且您可以在 sendSynchronous... 调用返回后立即编写它。

NSError * err;
NSURLResponse * response;
NSData * receivedData = [NSURLConnection sendSynchronousRequest:imageRequest
                                              returningResponse:&response
                                                          error:&err];
if( !receivedData ){
    /* Handle error */
}
/* Check response */

BOOL result = [receivedData writeToFile:fileOut atomically:YES];
/* check result, etc. */

关于objective-c - NSURLConnection 下载多张图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6027119/

相关文章:

objective-c - 如何在 Mac OS X 中过滤和覆盖文本输入

iphone - iOS 从 NSUserDefaults 调用电话号码

ios - 我可以为 UIButton 传递带有 @selector 的数组参数吗?

c - 缓冲字符串损坏

cocoa - 如何格式化/着色 NSTextView 字符串的技术

c - 如何在 Mac OSx 上处理来自外部程序的数据

objective-c - 在 Objective C 中绘制带有渐变的图表

带图像的 JavaScript 视频

java - 学习 XML 和 Java 的书

objective-c - NSString substringWithRange 返回错误的子字符串