如何将 CurrentLocation 与 GPS 坐标进行比较并在相等时显示消息?
Posted
技术标签:
【中文标题】如何将 CurrentLocation 与 GPS 坐标进行比较并在相等时显示消息?【英文标题】:How to Compare CurrentLocation to GPS Coordinate and Display a Message if Equal? 【发布时间】:2015-11-28 20:44:11 【问题描述】:我正在尝试创建一个最终会在某些位置振动的应用。我这周刚开始学习 Objective-C,发现这个教程对初步测试很有用:http://www.appcoda.com/how-to-get-current-location-iphone-user/
我正在测试它,而不是振动,以便标签在指定坐标处发生变化。但是,当我运行该应用程序时,它不会更改标签。在 xCode 的底部调试输出栏中,它显示坐标,它们与我想要的相同,但没有将标签“For Latitude Value”更改为“Success”,它什么也没有改变。这是当前代码:
// ViewController.m
#import "ViewController.h"
@import CoreLocation;
@interface ViewController ()<CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLGeocoder *geocoder;
@property (strong, nonatomic) CLPlacemark *placemark;
@end
@implementation ViewController
CLLocationManager *locationManager;
- (void)requestAlwaysAuthorization
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
locationManager = [[CLLocationManager alloc] init];
if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
[locationManager requestAlwaysAuthorization];
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
NSLog(@"%@", [locations lastObject]);
- (IBAction)getCurrentLocation:(id)sender
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
NSLog(@"didFailWithError: %@", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
NSLog(@"didUpdateLocations: %@", newLocation);
CLLocation *currentLocation = newLocation;
if ((currentLocation.coordinate.longitude == 51.50998000)&&(currentLocation.coordinate.latitude == -0.13370000))
self.longitudeLabel.text = [NSString stringWithFormat:@"success"];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
@end
如果有帮助,这里是 .h:
// ViewController.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController <CLLocationManagerDelegate>
@property (weak, nonatomic) IBOutlet UILabel *latitudeLabel;
@property (weak, nonatomic) IBOutlet UILabel *longitudeLabel;
@property (weak, nonatomic) IBOutlet UILabel *addressLabel;
- (IBAction)getCurrentLocation:(id)sender;
@end
我也试过了:
if (currentLocation != nil)
longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
就像他们在教程中所做的那样,它应该更改标签以显示 GPS 坐标,但它们也不会改变。同样,它只是在调试栏中显示 GPS 坐标。
关于为什么这不起作用的任何想法?如果这已经在某处被覆盖,我深表歉意,我花了几个小时在网上搜索和尝试解决方案,但由于我是新手,我可能不知道要搜索的正确术语。非常感谢任何建议!
【问题讨论】:
你能确认locationManager:didUpdateToLocation:fromLocation:
方法被调用了吗?
好问题 - 我不完全确定我会如何做到这一点,但如果这不起作用,那可能会解释一些事情。我尝试添加 NSLog(@"didUpdateLocations: %@", fromLocation);在 NSLog(@"didUpdateLocations: %@", newLocation); 下,但这导致构建失败。
你不能使用%@
来格式化CLLocation
,因为CLLocation
不是一个类,它是一个struct
。
是否有可能因为新位置必须与旧位置不同才能调用函数而没有调用它? (不确定是否是这种情况,但我无法从代码中分辨出来。)我并不关心比较新旧位置,我只想将当前位置与指定坐标进行比较。因此,我应该更改函数- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
吗?
【参考方案1】:
我不建议比较两个双精度值是否相等。从理论上讲,他们永远不会平等。更好的方法是检查该位置是否足够靠近您的参考位置。下面是我的代码库中的一个示例。这是来自我与实用程序函数一起使用的 C 文件。这里它处理浮点值,但你可以对双精度值做同样的事情。
int relativelyClose(CGFloat value, CGFloat reference, CGFloat precision)
return fabs(value - reference) / reference < range;
int relativelyClosePoints(CGPoint point, CGPoint r, CGFloat precision)
CGFloat dx = point.x -r.x;
CGFloat dy = point.y-r.y;
CGFloat distance = sqrt(dx*dx + dy*dy);
CGFloat reflength = sqrt(r.x*r.x + r.y*r.y);
return (distance < reflength * precision);
此外,为了确保设置标签值在主线程上执行,您可以像这样包装这些调用:
dispatch_async(dispatch_get_main_queue(), ^
longitudeLabel.text = ...;
latitudeLabel.text = ....;
);
【讨论】:
谢谢鲁迪,我很感激!无论如何,我要让它接受最终足够接近的值,所以我现在不妨这样做。干杯!不幸的是它不会影响当前的问题,但它绝对是一个很好的补充。 如果驱动蜂鸣器有效但更新 UI 无效,则可能是委托方法是从主线程之外的另一个线程调用的。对 UI 的更改必须在主线程上执行。您可以通过像这样包装文本设置代码来确保在主线程上执行:我无法在此处添加代码,因此我将编辑我的答案以包含此内容。以上是关于如何将 CurrentLocation 与 GPS 坐标进行比较并在相等时显示消息?的主要内容,如果未能解决你的问题,请参考以下文章
在没有互联网的情况下使用 iPhone GPS 更新用户位置