0

NSOperation のサブクラスを使用して、いくつかのバックグラウンド プロセスを実行しています。ユーザーがボタンをクリックしたときに操作をキャンセルしたい。

これが私の NSOperation サブクラスの外観です

- (id)init{
    self = [super init];
    if(self){
        //initialization code goes here
        _isFinished = NO;
        _isExecuting = NO;
    }

    return self;
}

- (void)start
{
    if (![NSThread isMainThread])
    {
        [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
        return;
    }
    [self willChangeValueForKey:@"isExecuting"];
    _isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];

    //operation goes here
}

- (void)finish{
    //releasing objects here

    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];

    _isExecuting = NO;
    _isFinished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
}

- (void)cancel{
    [self willChangeValueForKey:@"isCancelled"];

    [self didChangeValueForKey:@"isCancelled"];
    [self finish];
}

これが、このクラスのオブジェクトをキューに追加し、KVO 通知をリッスンする方法です。

operationQueue = [[NSOperationQueue alloc] init]; [operationQueue setMaxConcurrentOperationCount:5]; [operationQueue addObserver:self forKeyPath:@"operations" options:0 context:&OperationsChangedContext];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == &OperationsChangedContext) {
        NSLog(@"Queue size: %u", [[operationQueue operations] count]);
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

操作をキャンセルするには (たとえば、ボタンのクリックで)、-cancel を呼び出してみましたが、違いはありません。-finish も呼び出してみましたが、それでも何も変わりません。

操作をキューに追加するたびに、キューのサイズが増加するだけです。finish が呼び出されます (NSLog ステートメントを使用してチェックされます) が、操作は実際には終了しません。私はまだこれを正しく行っていると確信していません

誰かが私が間違っているところを教えてもらえますか?

どうもありがとう

4

2 に答える 2

2

NSOperation クラスリファレンスから:

操作をキャンセルしても、実行中の操作がすぐに強制的に停止されるわけではありません。すべての操作で isCancelled によって返される値を尊重することが期待されますが、コードはこのメソッドによって返される値を明示的にチェックし、必要に応じて中止する必要があります

つまり、cancel実装でこれが強制されない限り、メソッドは実際には操作をキャンセルしません。繰り返しますが、関連セクションから:

- (void)cancel

このメソッドは、オペレーション コードを強制的に停止しません。代わりに、オブジェクトの内部フラグを更新して、状態の変化を反映します。

于 2009-11-20T15:39:15.083 に答える
0

それを達成するには、次のものが必要です。

NSOperation サブクラスで、main メソッドに追加します

 while (! self.isCancelled) {
  [NSThread sleepForTimeInterval:1];
 }

GUI クラスでは、NSOperation サブクラスへのインスタンス変数が必要であり、ボタンを管理するメソッドでは、NSOperation サブクラスをキャンセルします。例えば:

- (IBAction) clickButton: (UIBarButtonItem *) item{
 [myOperation cancel]; 
}
于 2010-06-17T00:18:37.133 に答える