-2

私はいくつかのアドレスを持っているとしましょう。サイクル内の各アドレスの座標を取得する必要があります。ただし、1 つの住所の座標を取得するには時間がかかります。1サイクルで座標を非同期に取得する方法は?

4

1 に答える 1

5

可変配列から単一の住所をジオコーディングするルーチンを作成し、それ自体を呼び出して完了ブロック内の次の住所を処理することができます。したがって:

- (void)nextGeocodeRequest {
    // if we're done, dp whatever you want

    if ([self.addresses count] == 0) {
        // do whatever you want when we're done (e.g. open maps)

        return;
    }

    // if not, get the next address to geocode from NSMutableArray and
    // remove it from list of addresses to process

    NSString *address = self.addresses[0];
    [self.addresses removeObjectAtIndex:0];

    // geocode the address

    CLGeocoder *geocoder = [[CLGeocoder alloc]init];

    [geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {

        // do whatever you want for the individual geocode process

        // when all done, queue up the next geocode address

        [self nextGeocodeRequest];
    }];
}

または、より複雑な操作キューを使用できます。

- (void)geocodeAddresses:(NSArray <NSString *>*)addresses {
    CLGeocoder *geocoder = [[CLGeocoder alloc]init];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;
    queue.name = @"com.domain.app.geocode";

    NSOperation *finalCompletionOperation = [NSBlockOperation blockOperationWithBlock:^{
        // do whatever you want when all done
        NSLog(@"done");
    }];

    for (NSString *address in addresses) {
        // create a block for the geocode request completion block

        NSOperation *geocodeOperation = [[GeocodeOperation alloc] initWithGeocoder:geocoder Address:address geocodeCompletionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
            if (error) {
                NSLog(@"error = %@", error);
            } else {
                NSLog(@"placemarks = %@", placemarks);
            }
        }];

        // The final completion block is contingent on the completion of this geocode request completion block

        [finalCompletionOperation addDependency:geocodeOperation];

        // let's queue the geocode request

        [queue addOperation:geocodeOperation];
    }

    [queue addOperation:finalCompletionOperation];
}

ここで、GeocodeOperation.h:

#import "AsynchronousOperation.h"
@import CoreLocation;

NS_ASSUME_NONNULL_BEGIN

@interface GeocodeOperation : AsynchronousOperation

@property (readonly, nonatomic, copy) NSString *address;

- (instancetype)initWithGeocoder:(CLGeocoder *)geocoder Address:(NSString *)address geocodeCompletionHandler:(CLGeocodeCompletionHandler) geocodeCompletionHandler;

@end

NS_ASSUME_NONNULL_END

そして、GeocodeOperation.m:

#import "GeocodeOperation.h"

@interface GeocodeOperation ()
@property (nonatomic, strong) CLGeocoder *geocoder;
@property (nonatomic, copy, nonnull) NSString *address;
@property (nonatomic, copy) CLGeocodeCompletionHandler geocodeCompletionHandler;
@end

@implementation GeocodeOperation

- (instancetype)initWithGeocoder:(CLGeocoder *)geocoder Address:(NSString * _Nonnull)address geocodeCompletionHandler:(CLGeocodeCompletionHandler) geocodeCompletionHandler  {
    self = [super init];
    if (self) {
        self.geocoder = geocoder;
        self.address = address;
        self.geocodeCompletionHandler = geocodeCompletionHandler;
    }
    return self;
}

- (void)main {
    [self.geocoder geocodeAddressString:self.address completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        self.geocodeCompletionHandler(placemarks, error);
        [self completeOperation];
    }];
}

- (void)cancel {
    [self.geocoder cancelGeocode];
    [super cancel];
}

@end

そしてAsynchronousOperation.h

@interface AsynchronousOperation : NSOperation

/// Complete the asynchronous operation.
///
/// This also triggers the necessary KVO to support asynchronous operations.

- (void)completeOperation;

@end

そしてAsynchronousOperation.m

//
//  AsynchronousOperation.m
//

#import "AsynchronousOperation.h"

@interface AsynchronousOperation ()

@property (getter = isFinished, readwrite)  BOOL finished;
@property (getter = isExecuting, readwrite) BOOL executing;

@end

@implementation AsynchronousOperation

@synthesize finished  = _finished;
@synthesize executing = _executing;

- (instancetype)init {
    self = [super init];
    if (self) {
        _finished  = NO;
        _executing = NO;
    }
    return self;
}

- (void)start {
    if (self.isCancelled) {
        if (!self.isFinished) self.finished = YES;
        return;
    }

    self.executing = YES;

    [self main];
}

- (void)completeOperation {
    if (self.isExecuting) self.executing = NO;
    if (!self.isFinished) self.finished  = YES;
}

#pragma mark - NSOperation methods

- (BOOL)isAsynchronous {
    return YES;
}

- (BOOL)isExecuting {
    @synchronized(self) { return _executing; }
}

- (BOOL)isFinished {
    @synchronized(self) { return _finished; }
}

- (void)setExecuting:(BOOL)executing {
    [self willChangeValueForKey:@"isExecuting"];
    @synchronized(self) { _executing = executing; }
    [self didChangeValueForKey:@"isExecuting"];
}

- (void)setFinished:(BOOL)finished {
    [self willChangeValueForKey:@"isFinished"];
    @synchronized(self) { _finished = finished; }
    [self didChangeValueForKey:@"isFinished"];
}

@end
于 2013-01-13T13:44:07.317 に答える