0

我有一个处理NSURLConnection的Download对象。

然后我有NSOperation对象(DownloadOperation),它将下载对象作为属性。

下载对象具有启动/暂停/恢复/取消的能力。

这是DownloadOperation的主要方法

- (void)main
{
    @autoreleasepool {

        BOOL isDone = NO;

        if (![self isCancelled]) {   
            [_download start]; //Download object start (creates NSURLConnection internally)
        }

        NSDate *distantFuture = [NSDate distantFuture];
        while(!isDone && ![self isCancelled]) {

            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:distantFuture];

            if (!_download.isActive) { //internal state of Download
                isDone = YES;
            }
        }

        [self completeOperation]; //this sets finished and executing flags
    }
}

从外部(从 UI),我使用Download对象进行操作:StartPauseResumeCancel。在内部我正在改变它的状态,所以当下载完成或取消时,isActive设置为NO并且 while 循环应该结束。

如果我开始下载并让它完成(在后台,NSURLConnection完成并调用委托 - connectionDidFinish ...) ,这将起作用

如果我暂停/恢复 Download,下载将继续下载并完成(并更改其内部状态:isActive -> NO)。暂停时我取消NSURLConnection并在恢复时创建新的。

或者如果我取消下载,它也将处于非活动状态(NSURLConnection被取消)。

但问题是:

[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:distantFuture];在这些情况下永远不会返回(当我取消NSURLConnection时)并且我的“ if ”语句永远不会被处理,所以这个DownloadOperation总是被认为正在运行并且永远不会退出我的NSOperationQueue

看起来没有可以触发的事件会导致 runloop 唤醒。

我试过

            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];

这种工作但不是那么顺利,我认为这不是最好的解决方案。

我真正想知道的是,如何强制NSRunLoop唤醒(如何触发一些会导致它唤醒的事件)并继续我的 while 循环?

4

1 回答 1

2

这就是我所做的。

好消息是我的应用程序中有通知,并且我确切地知道下载何时发生变化。所以我创建了一个实例变量NSThread currentThread,并在 main 的开头调用currentThread = [NSThread currentThread].

在我收到我知道应该导致我的线程唤醒的通知后,我打电话给:

[self performSelector:@selector(wakeUpThread:) onThread:currentThread withObject:nil waitUntilDone:NO];

- (void)wakeUpThread什么都不做,它是空方法,但这样做的目的是唤醒线程并导致我的运行循环继续。

于 2012-10-12T05:51:03.863 回答