2015-06-22 3 views
1

Я создал вспомогательный класс для своих потребностей в местоположении, поэтому я не нарушаю принцип DRY. Класс выглядит следующим образом:
Location.hЗадержка в Corelocation

@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 пытается создать экземпляр Место и установить широту и долготу метки , в методе viewDidLoad метки помещаются в 0,00000. По-видимому, для получения координат требуется около полутора секунд. Я попытался с помощью

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
     [self setCoordinateLabels]; 
    }); 

Но это только кажется очень Hacky и не может быть лучшей практикой? Так я могу сделать это лучше?

ответ

1

Хорошо - это очень хаки. Почему бы вам не переслать методы делегата?

locationManager:didUpdateToLocation: 

(Btw. Это наследие функция)

Сообщает вам, когда первое место установлено. Вы можете просто иметь массив делегатов в своем классе 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.. 
    }); 
}]; 
+0

Спасибо за быстрый ответ! :) Я ничего не видел о NSMapTable. Итак, первый пример первого примера (статический NSMapTable * listenerBlocks) отправляется в файл location.m И тогда я сделалUpdateToLocation (все еще в location.m справа?) Получить вторую часть кода. Какой метод я вызываю с помощью «eventName»? Я устанавливаю там этикетки? Или что? – 4FunAndProfit

+0

Забудьте о eventName - я обновляю экземпляр кода без него, вам это не нужно. Скопируйте мой отредактированный код! Я также добавил пример использования, где вы бы обновили свой ярлык. –

+0

Вам нужен NSMapTable для лучшего управления памятью, чем NSDictionary, но в основном то же самое. Слушателя просто не сохранится! –

Смежные вопросы