如何获得当前位置UIImagePickerController捕获图像?

我研究了如何从UIImagePickerController摄像头返回的图像中获取位置数据。 不过,我认为最简单的方法就是在UIImagePickerController捕获图像的时候从CLLocationManager获取当前位置。

有没有办法做到这一点? 有没有一种方法来听取“capturePhoto”事件?

只是为了澄清,使用我的应用程序的用户可能会移动得很快。

以下是我推荐的内容,因此您不必跟踪用户的位置,因此您可以将用户的位置与实际拍摄图像的时间最接近。

viewDidLoad实例化CLLocationManager类variables,例如:

 self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; 

并确保它的授权:

 if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedWhenInUse) { [self.locationManager requestWhenInUseAuthorization]; } 

(也包括.plist中的“NSLocationWhenInUseUsageDescription”键)

然后,您可以等到UIImagePickerController实际出现之前(1)初始化字典以保存位置和(2)开始更新位置,例如:

 [self presentViewController:self.imagePicker animated:YES completion:nil]; self.locationDictionary = [[NSMutableDictionary alloc] init]; [self.locationManager startUpdatingLocation]; 

此时,当从didUpdateToLocation委托方法返回CLLocation值时,可以开始将用户的更新位置存储在NSMutableDictionary self.locationDictionary类实例variables中,例如:

 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { // Format the current date time to match the format of // the photo's metadata timestamp string NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"YYYY:MM:dd HH:mm:ss"]; NSString *stringFromDate = [formatter stringFromDate:[NSDate date]]; // Add the location as a value in the location NSMutableDictionary // while using the formatted current datetime as its key [self.locationDictionary setValue:newLocation forKey:stringFromDate]; } 

然后,一旦图像被选中,在元数据中find它的时间戳,并find位置字典中具有最接近图像时间戳的时间戳密钥的值,例如:

 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { [self.locationManager stopUpdatingLocation]; // When a photo is selected save it as a UIImage self.selectedPhoto = info[UIImagePickerControllerOriginalImage]; // Get the timestamp from the metadata and store it as an NSString self.selectedPhotoDateTime = [[[info valueForKey:UIImagePickerControllerMediaMetadata] objectForKey:@"{Exif}"] objectForKey:@"DateTimeOriginal"]; // If the CLLocationManager is in fact authorized // and locations have been found... if (self.locationDictionary.allKeys.count > 0) { // Sort the location dictionary timestamps in ascending order NSArray *sortedKeys = [[self.locationDictionary allKeys] sortedArrayUsingSelector: @selector(compare:)]; // As a default, set the selected photo's CLLocation class // variable to contain the first value in the sorted dictionary self.selectedPhotoLocation = [self.locationDictionary objectForKey:[sortedKeys objectAtIndex:0]]; // Then go through the location dictionary and set the // photo location to whatever value in the dictionary // has a key containing a time most closely before // the image timestamp. Note that the keys can be compared // as strings since they're formatted in descending order -- // year to month to day to hour to minute to second. for (NSString *key in sortedKeys) { // If the photo's metadata timestamp is less than or equal to // the current key, set the selected photo's location class // variable to contain the CLLocation value associated with the key if ([self.selectedPhotoDateTime compare:key] != NSOrderedAscending) { self.selectedPhotoLocation = [self.locationDictionary objectForKey:key]; } // Else if the time in the location dictionary is past // the photo's timestamp, break from the loop else { break; } } } [self dismissViewControllerAnimated:YES completion:nil]; } 

在您的.h file您需要将以下内容添加到您的代码中:

 @interface TakePhotoViewController : UIViewController <CLLocationManagerDelegate> 

在您的.m file您需要以下内容。

 @interface TakePhotoViewController (){ //location stuff CLLocationManager * manager; CLGeocoder *geocoder; CLPlacemark * placemark; } 

上面的代码集的相关参考find你的位置。

接下来将其添加到您的viewDidLoad方法中:

 manager = [[CLLocationManager alloc] init]; geocoder = [[CLGeocoder alloc] init]; 

这初始化了位置pipe理器和地理编码器。

然后在您的代码中启动拍照或将图片返回到视图使用此:

 manager.delegate = self; manager.desiredAccuracy = kCLLocationAccuracyBest; [manager startUpdatingLocation]; 

要停止位置的连续更新,请将其添加到imagePickerReturn方法中:

 [manager stopUpdatingLocation]; 

只要您停止更新位置,您将保存最新的位置。 该位置每隔0.5-1秒更新一次,因此即使您正在移动或长时间打开相机,它也只会存储您select的任何图像的位置。 要保存date(其中包括时间下降到毫秒)使用:

 NSDate * yourCoreDataDateName = [NSDate date]; 

对于良好的编码习惯来处理任何错误,你将需要这个:

 //handles the error if location unavailable - (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; self.locationTF.text = @"Finding Location..."; if (currentLocation != nil){ [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) { if (error == nil && [placemarks count] > 0){ placemark = [placemarks lastObject]; //the code below translates the coordinates into readable text of the location self.locationLabel.text = [NSString stringWithFormat:@"%@ %@ , %@, %@, %@ %@", placemark.subThoroughfare, placemark.thoroughfare, placemark.locality, placemark.administrativeArea, placemark.country, placemark.postalCode]; } else{ NSLog(@"%@", error.debugDescription); self.locationLabel.text = @"Failed to find location"; } }]; } } 

我必须警告你,iOS8将无法find一个位置,因为它需要你作为程序员添加一个警报视图来授权获取位置,将抛出没有错误。 请参阅本教程以了解如何解决此问题:

http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

我从最受欢迎的关于新错误的问题中得到了这个教程。

最准确的方法是通过exif元数据。 请看Ole Begemann在这篇文章中关于如何做到这一点。

UPDATE

看起来像苹果不包括元数据的位置从UIImagePicker使用相机拍摄的图像。

获取图像的位置的另一个选项是使用UIImagePicker的自定义覆盖视图,并在调用takePicture方法时获取位置。 这可能会达到最好的结果。