假设我有几个地址。我需要获取循环中每个地址的坐标。但是获取一个地址的坐标需要一些时间。如何在一个周期内异步获取坐标?
问问题
1293 次
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 回答