【问题标题】:Set progress bar for downloading NSData设置下载 NSData 的进度条
【发布时间】:2013-11-07 09:14:02
【问题描述】:
NSURL *url = [NSURL URLWithString:@"http://i0.kym-cdn.com/entries/icons/original/000/005/545/OpoQQ.jpg?1302279173"]; 
NSData *data = [NSData dataWithContentsOfURL:url]; 
imageView.image = [[[UIImage imageWithData:data];

我想在下载时设置进度条。

【问题讨论】:

  • 您可以使用AFNetworking,但如果您不想要第三方库,@richy 对这个问题的回答可能对stackoverflow.com/questions/10480815/… 有所帮助。
  • 只有在后台线程中运行上述代码并且在该后台线程内使用计时器定期检查 NSData 长度并更新主线程上的进度条值时,才能显示上述代码的进度条(仅当您提前知道 NSData 长度时才有效,否则您必须使用 Async NSURLconnection 来获取确切的文件大小)。
  • 不确定反对票是为了什么?顺便说一句,我建议避免使用 AFNetworking 等第三方框架。至少在您能够自如地编写自己的网络之前。即使那样,我也会避开它们。我更喜欢调试自己的代码而不是别人的。
  • @Dinesh 他如何获得预期的数据长度以设置完成百分比?
  • @Fogmeister 更新了我的评论并感谢您指出这一点。

标签: ios xcode4.5


【解决方案1】:

举个更详细的例子:

在你的 .h 文件中做

@interface YourClass : YourSuperclass<NSURLConnectionDataDelegate>

在你的 .m 文件中做

@property (nonatomic) NSMutableData *imageData;
@property (nonatomic) NSUInteger totalBytes;
@property (nonatomic) NSUInteger receivedBytes;

在某处打电话

NSURL *url = [NSURL URLWithString:@"http://i0.kym-cdn.com/entries/icons/original/000/005/545/OpoQQ.jpg?1302279173"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

并且还实现了委托方法

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) urlResponse;
    NSDictionary *dict = httpResponse.allHeaderFields;
    NSString *lengthString = [dict valueForKey:@"Content-Length"];
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    NSNumber *length = [formatter numberFromString:lengthString];
    self.totalBytes = length.unsignedIntegerValue;

    self.imageData = [[NSMutableData alloc] initWithCapacity:self.totalBytes];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.imageData appendData:data];
    self.receivedBytes += data.length;

    // Actual progress is self.receivedBytes / self.totalBytes
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    imageView.image = [UIImage imageWithData:self.imageData];
}

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

【讨论】:

  • 您在这里使用的方法不正确。您应该使用 NSURLConnectionDownloadDelegate 来报告进度。这就是它的用途。见我的要点。
  • 我从工作代码中提取了这个。我想这些是正确的方法。
  • 我想你可以使用那个方法。 “正确”的方式是使用下载委托。
  • 老实说我不这么认为。下载委托适用于由 Newsstand Kit 创建的 NSURLConnections。在我(和您)的实现中,NSURLConnection 是手动创建的,因此数据委托更适合。
  • 啊,也许你是对的。不知道。我以前用过这个,但错过了 NewsStand 位。其实你很有可能是对的。
【解决方案2】:

您无法使用该方法获得进度回调。

您需要使用NSURLConnectionNSURLConnectionDataDelegate

NSURLConnection 然后异步运行并向其委托发送回调。

主要看的是……

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

这些都用于获取连接以执行您已经在执行的操作。

编辑

实际上,请参阅下面 Marc 的回答。没错。

【讨论】:

  • ..或者他可以把这个下载放到dispatch_async块中,在里面调用下载;>
  • 是的,但他不会从中获得实际进展。他只能知道什么时候完成。
  • 对,他想要一个酒吧,而不仅仅是一个纺车。为你 +1 @Fogmeister
【解决方案3】:

您可以使用 MBProgress Hud 类来加载视图。您只能从这里下载两个课程:-https://github.com/jdg/MBProgressHUD 在要加载数据的类中编写此代码后 示例:在你的 viewDidLoad 你写这个

- (void) viewDidLoad
{
    MBProgressHud *spinner =  [MBProgressHUD showHUDAddedTo:self.view animated:YES];

        spinner.mode = MBProgressHUDModeCustomView;

        [spinner setLabelText:@"Loading....."];

        [spinner setLabelFont:[UIFont systemFontOfSize:15]];

        [spinner show:YES];

        [self performSelectorInBackground:@selector(getData) withObject:nil];
}

- (void) getData
{
     NSURL *url = [NSURL URLWithString:@"http://i0.kym-cdn.com/entries/icons/original/000/005/545/OpoQQ.jpg?1302279173"]; 

        NSData *data = [NSData dataWithContentsOfURL:url]; 

        imageView.image = [[[UIImage imageWithData:data];

        [spinner hide:YES];

        [spinner removeFromSuperViewOnHide];
}

【讨论】:

  • 这只会显示一个微调器。不是进度条。你也可以用一个简单的活动指示器视图来做到这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
相关资源
最近更新 更多