0

私はUITextfieldとを持っていUIButtonます。たとえば、ユーザーは「犬」や「猫」などの検索語を入力すると、カスタム ディスパッチ GCD キューで実行される別のクラスのメソッドがトリガーされ、画像 (約 100 程度) がフェッチされます。

ユーザーがフェッチ中に「cat」などの別の検索語を変更して入力し、フェッチ ボタンを押した場合を除いて、すべて正常に動作します。フェッチ中にそのスレッド/メソッドを停止できるようにしたいと考えています。前の検索語からの画像。

私はNSThread(以前に使用したことのないもの)またはブロック(メソッドの実行が終了したときに通知を受けるため)について考えましたが、ブロックの問題は、メソッドがその処理を完了すると通知を受け取ることですが、ここで必要なものフェッチを停止するように指示することです (ユーザーが別の検索を決定し、別の検索語を入力したため)。

終了する前にカスタム GCD スレッドで実行されているループ/メソッドを停止する方法について、誰かが私にいくつかのサンプルを引用できますか? 前もって感謝します。

4

2 に答える 2

1

と を使用NSOperationNSOperationQueueて、バックグラウンドでマップ上のマーカーをクラスター化し、必要に応じて操作をキャンセルしています。マーカーをクラスター化する関数は、次のサブクラスで実装されますNSOperation

ClusterMarker.h:

@class ClusterMarker;

@protocol ClusterMarkerDelegate <NSObject>

- (void)clusterMarkerDidFinish:(ClusterMarker *)clusterMarker;

@end

@interface ClusterMarker : NSOperation

-(id)initWithMarkers:(NSSet *)markerSet delegate:(id<ClusterMarkerDelegate>)delegate;
// the "return value"
@property (nonatomic, strong) NSSet *markerSet;
// use the delegate pattern to inform someone that the operation has finished
@property (nonatomic, weak) id<ClusterMarkerDelegate> delegate;

@end

および ClusterMarker.m:

@implementation ClusterMarker

-(id)initWithMarkers:(NSSet *)markerSet delegate:(id<ClusterMarkerDelegate>)delegate
{
    if (self = [super init]) {
        self.markerSet = markerSet;
        self.delegate = delegate;
    }
    return self;    
}

- (void)main {
    @autoreleasepool {

        if (self.isCancelled) {
            return;
        }

        // perform some Überalgorithmus that fills self.markerSet (the "return value")

        // inform the delegate that you have finished
        [(NSObject *)self.delegate performSelectorOnMainThread:@selector(clusterMarkerDidFinish:) withObject:self waitUntilDone:NO];
    }
}

@end

コントローラーを使用してキューを管理できます。

self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.name = @"Überalgorithmus.TheKillerApp.makemyday.com";
// make sure to have only one algorithm running
self.operationQueue.maxConcurrentOperationCount = 1;

操作をキューに入れたり、以前の操作を強制終了したりします。

ClusterMarker *clusterMarkerOperation = [[ClusterMarker alloc] initWithMarkers:self.xmlMarkerSet delegate:self];
// this sets isCancelled in ClusterMarker to true. you might want to check that variable frequently in the algorithm
[self.operationQueue cancelAllOperations];
[self.operationQueue addOperation:clusterMarkerOperation];

操作が終了したときにコールバックに応答するには:

- (void)clusterMarkerDidFinish:(ClusterMarker *)clusterMarker
{
    self.clusterMarkerSet = clusterMarker.markerSet;

    GMSProjection *projection = [self.mapView projection];
    for (MapMarker *m in self.clusterMarkerSet) {
        m.coordinate = [projection coordinateForPoint:m.point];
    }

//    DebugLog(@"now clear map and refreshData: self.clusterMarkerSet.count=%d", self.clusterMarkerSet.count);
    [self.mapView clear];
    [self refreshDataInGMSMapView:self.mapView];
}

私の記憶が正しければ、raywenderlich.comのこのチュートリアルをスターターとして使用しました。

于 2013-06-29T19:40:40.800 に答える
0

現在実行中の操作をキャンセルする cancel メソッドがあるため、 NSOperation を使用することをお勧めします。

于 2013-06-29T13:45:01.743 に答える