0

NSURLConnectionを処理するDownloadオブジェクトがあります。

次に、 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を終了しません。

その実行ループを起動させる可能性のあるイベントが発生しないようです。

私は試した

            [[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 に答える