1

我正在制作一个显示动画 UIImageView 的应用程序,作为指示应用程序繁忙的自定义方式。我正在使用 NSOperationQueue 进行文件上传,并且我希望 UIImageView 在队列中有内容时显示。当队列中的每个操作完成时,我想删除 UIImageView。

我认为这很容易做到,但过去一个小时我一直被困住。显示 UIImageView 真的很容易,但我似乎无法删除它。这可能是我忽略的非常简单的事情。这是我的代码。谢谢!:)

- (void)viewDidLoad {
    //set up the uiimageview
    self.spinnerView = [[UIImageView alloc] initWithFrame:CGRectMake([[UIScreen mainScreen] bounds].size.width-44,0,44,44)];
    self.spinnerView.animationImages = [NSArray arrayWithObjects:
                                     [UIImage imageNamed:@"0.gif"],
                                     [UIImage imageNamed:@"1.gif"],
                                     [UIImage imageNamed:@"2.gif"],
                                     [UIImage imageNamed:@"3.gif"],
                                     [UIImage imageNamed:@"4.gif"], nil];
    self.spinnerView.animationDuration = 0.5f;
    self.spinnerView.tag = 998;
    self.spinnerView.animationRepeatCount = 0;
    [self.view addSubview: self.spinnerView];

    //set up the queue
    self.uploadQueue = [[NSOperationQueue alloc] init];
    [self.uploadQueue setMaxConcurrentOperationCount:1];

    //set up observer for the queue
    [self.uploadQueue addObserver:self forKeyPath:@"operationCount" options:NSKeyValueObservingOptionNew context:NULL];
}


- (void)newUpload:(NSData*)data {
    [self.spinnerView startAnimating];
    //....
    //request is a NSURLRequest that's set up in this method
    [NSURLConnection sendAsynchronousRequest:request queue:self.uploadQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    }];
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                     change:(NSDictionary *)change context:(void *)context
{
    if (object == self.uploadQueue && [keyPath isEqualToString:@"operationCount"]) {
        if (self.uploadQueue.operationCount == 0) {
            [self.spinnerView stopAnimating];
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object
                           change:change context:context];
    }

我这样做正确吗?有更好的方法吗?我已经在这里停留了一段时间,并且开始认为可能不是 UIImageView 搞砸了,而是我将 NSURLRequests 添加到 NSOperationQueue 的方式。

再次感谢!

4

3 回答 3

1

你为什么不试试https://github.com/samvermette/SVProgressHUDhttps://github.com/jdg/MBProgressHUD?它们正是为此目的而制作的(在执行某些异步工作时显示模态加载窗口)。它们既易于使用,又易于为您的图像和许多其他选项定制。

于 2013-07-18T00:05:02.477 回答
0

的文档说,只有在异步 URL 请求完成sendAsynchronousRequest:queue:completionHandler:,才会将操作添加到指定的操作队列中。这个操作只是一个完成块。

所以我认为你并没有真正按照你想要的方式添加添加操作到你的队列中。URL 请求将在队列外的它们自己的线程上运行,只有完成块放在队列中。如果您没有在完成块本身中指定任何内容,那么它甚至可能根本没有添加到队列中?

无论哪种方式,我认为您不会将 5 个 URL 操作添加到队列中,然后依次执行operationCount== 5、4、3、2、1、0。您更有可能同时触发 5 个 URL 请求与他们的完成块在其 URL 请求碰巧完成后以不确定的顺序添加到队列中。


做我认为你打算做的事情,你可以:

  1. 编写一个包含和管理等的“并发”子类。 NSOperationNSURLConnectionNSURLRequest
  2. 使用AFNetworking.
  3. 继续sendAsynchronousRequest:queue:completionHandler:但使用一个操作的完成处理程序来启动下一个请求,并使用最后一个请求的完成处理程序来停止微调器。您可以在这里使用主队列,因为队列中唯一要做的工作是开始下一个操作或停止微调器。无论如何,URL 请求的实际工作都是在它自己的线程上完成的。

编写自己的并发 NSOperation 有点棘手,我自己编写了一个,但我可能应该只使用 AFNetworking。如果满足您的需求,选项 3 可能是最快的。

于 2013-07-19T08:43:58.027 回答
0

将此添加到您的 .h 文件中:UIImageView *spinnerView;在您的 .m 文件中,您需要在您的 .m 文件中添加类似的内容-(void)newUpload

if (code that says file uploads are done) {
spinnerView.hidden = YES;
}
于 2013-07-18T00:02:19.847 回答