iOS: остановка потока/метода в середине процесса

У меня есть UITextfield и UIButton. Пользователь может ввести, например, слово для поиска, такое как «собака» или «кошка», и это вызовет вызов метода в другом классе, который запускается в настраиваемой очереди GCD отправки для извлечения изображений (около 100 или так).

Все работает нормально, за исключением того, что пользователь в разгар выборки решает изменить и ввести другое поисковое слово, такое как «кошка», а затем нажать кнопку выборки, я хотел бы иметь возможность остановить этот поток/метод во время выборки изображения из предыдущего поискового запроса.

Я думал о NSThread (что-то, что я никогда раньше не использовал) или блоках (чтобы получать уведомления после завершения работы метода), но проблема с блоками в том, что я получу уведомление, как только метод завершит свою работу, но что мне нужно здесь, чтобы остановить выборку (поскольку пользователь выбрал другой поиск и ввел другой поисковый запрос).

Может ли кто-нибудь процитировать меня с некоторыми примерами того, как мы можем остановить цикл/метод, пока он выполняется в пользовательском потоке GCD, прежде чем он будет завершен? Заранее спасибо.


person Unheilig    schedule 29.06.2013    source источник


Ответы (2)


Я использую NSOperation и NSOperationQueue для кластеризации маркеров на карте в фоновом режиме и для отмены операции при необходимости. Функция кластеризации маркеров реализована в подклассе NSOperation:

КластерМаркер.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 как стартовый.

person user511    schedule 29.06.2013

Я бы рекомендовал использовать NSOperation, так как у него есть метод отмены, который отменит текущую операцию.

person ldindu    schedule 29.06.2013
comment
Если вы используете NSOperation, обязательно проверьте isCancelled в своем коде, чтобы определить, когда следует прервать. - person mttrb; 29.06.2013