我为我的位置需求创建了一个帮助程序类,所以我没有违反DRY原则。这个类看起来像这样:
Location.h
@interface Location : NSObject <CLLocationManagerDelegate>{
CLLocationManager *manager;
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
-(float)latitude;
-(float)longitude;
-(NSString *)postalcode;
Location.m
@implementation Location{
float latitude;
float longitude;
NSString *postalcode;
}
-(id)init{
NSLog(@"Hallo");
[self setupLocationManager];
return self;
}
-(float)latitude{
return latitude;
}
-(float)longitude{
return longitude;
}
-(NSString *)postalcode{
return postalcode;
}
-(void)setupLocationManager{
manager = [[CLLocationManager alloc] init];
[manager requestWhenInUseAuthorization];
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
manager.distanceFilter = 100;
[manager startUpdatingLocation];
geocoder = [[CLGeocoder alloc] init];
}
#pragma mark - CLLocationManagerDelegate Methods
- (void)locationManager:(CLLocationManager *)manager didFailWithError: (NSError *)error
{
NSLog(@"Error: %@", error);
NSLog(@"Failed to get location! :(");
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(@"Location: %@", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
latitude = currentLocation.coordinate.latitude;
longitude = currentLocation.coordinate.longitude;
}
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
postalcode = [NSString stringWithFormat:@"%@",placemark.postalCode];
/*
self.address.text = [NSString stringWithFormat:@"%@ %@\n%@ %@\n%@\n%@",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
*/
} else {
NSLog(@"%@", error.debugDescription);
}
} ];
}
@end
当我在ViewController中尝试创建Location实例并设置纬度和经度标签时,在viewDidLoad方法中,标签的值为0.00000。 显然,获取坐标需要大约半秒钟的位置。 我尝试过使用
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self setCoordinateLabels];
});
但是,这看起来非常hacky并且可能不是最好的做法?那么有什么方法可以做到这一点更好吗?
答案 0 :(得分:1)
嗯 - 这非常hacky。你为什么不转发你的委托方法电话?
locationManager:didUpdateToLocation:
(顺便说一下,这是遗留功能)
告诉您何时设置了第一个位置。您可以在Location
课程中拥有一系列代表,并在适当的时候致电每位代表。
以下是块的示例:
static NSMapTable *listenerBlocks;
+ (void)addListener:(NSObject *)listener listenerBlock:(void (^)())listenerBlock
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
listenerBlocks =
[NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory
valueOptions:NSMapTableStrongMemory];
});
if (listenerBlock && listener) {
[listenerBlocks setObject:listenerBlock forKey:listener];
}
}
+ (void)removeListener:(NSObject *)listener
{
if (listener) {
[listenerBlocks removeObjectForKey:listener];
}
}
在locationManager:didUpdateToLocation:
中,您只需致电
NSArray *allBlocks = [[listenerBlocks objectEnumerator] allObjects];
for(void (^listenerBlock)(NSString *) in allBlocks)
{
listenerBlock();
}
最后
在需要更新标签的类中(例如myLabel
):
[Location addListener:self listenerBlock:^{
dispatch_async(dispatch_get_main_queue(),^{
//myLabel.text = //... update your label here
[self setCoordinateLabels]; // as from your code above..
});
}];