iphone - 在没有 NSTimer 的情况下每隔几秒调用一次获取当前坐标

标签 iphone objective-c ios ios6 core-location

我知道如何使用 NSTimer 进行此操作,但我不想每隔几秒钟就没有计时器就获取当前的 iPhone 坐标。我无法使用计时器,因为我在应用程序处于后台时获取坐标。
我尝试过一些东西,但这不是每 10 秒,而是每秒调用一次,因为我不想。
我在这里做错了什么?

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *loc = [locations objectAtIndex:0];

    NSDate* eventDate = loc.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (howRecent < 10)
    {
        CLLocation* location = [locations lastObject];

        double lat = location.coordinate.latitude;
        double lng = location.coordinate.longitude;
        NSLog(@"lat:%f lng:%f", lat, lng);

首先尝试每 10 秒执行一次后台任务,但如果我在这里做任何事情,不知道在哪里设置时间:
- (void)applicationDidEnterBackground:(UIApplication *)application
{

    backgroundTask = [application beginBackgroundTaskWithExpirationHandler: ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (backgroundTask != UIBackgroundTaskInvalid)
            {
                [application endBackgroundTask:backgroundTask];
                backgroundTask = UIBackgroundTaskInvalid;
            }
        });
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        _pendingLocationsTimer = [NSTimer timerWithTimeInterval:_pendingLocationsTimerDuration
                                                         target:self
                                                       selector:@selector(_acceptBestAvailableLocation:)
                                                       userInfo:nil repeats:NO];


        NSRunLoop *loop = [NSRunLoop currentRunLoop];
        [loop addTimer:_pendingLocationsTimer forMode:NSRunLoopCommonModes];
        [loop run];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (backgroundTask != UIBackgroundTaskInvalid)
            {
                // if you don't call endBackgroundTask, the OS will exit your app.
                [application endBackgroundTask:backgroundTask];
                backgroundTask = UIBackgroundTaskInvalid;
            }
        });
    });

}

最佳答案

我在后台状态下遇到计时器问题。不能保证你会有一个事件的运行循环,所以在你回到前台之前计时器永远不会触发。我所做的是:

 NSRunLoop *loop = [NSRunLoop currentRunLoop];
 [loop addTimer:myTimer forMode:NSRunLoopCommonModes];
 [loop run];

我在 BackgroundIdentifierTask 开始和结束调用中的后台线程上执行此操作。我并不完全相信我的所有内容都是正确的,事实上,我查看了您的问题,看看答案是否可以帮助我确认或纠正我对要求的理解。

如果您想持续监控位置,您还必须在默认 info.pList 中启用位置服务的后台模式。如果您只是使用重要位置更新或地理围栏,则不需要它。

我的计时器确实可以正常工作,并且按照这种方式进行设置。在此之前它不能可靠地工作。

除此之外,您最好不要使用计时器。使用上面的代码,只需更改位置管理器的属性。所需的准确度和距离过滤器是降低管理器发送新位置通知频率的属性。

请参阅我刚刚在 github 上为感兴趣的任何人发布的我自己的位置处理程序示例:

http://github.com/dsdavids/TTLocationHandler

我不认为计时器是关键。如果你在你的项目中删除了 TTLocationHandler 类,那么看看 LMViewController 类如何响应处理程序。
NSNotificationCenter *defaultNotificatoinCenter = [NSNotificationCenter defaultCenter];
[defaultNotificatoinCenter addObserver:self selector:@selector(handleLocationUpdate) name:LocationHandlerDidUpdateLocation object:nil];

将 Controller 设置为观察者。每当处理程序确定已收到新的或更准确的位置时,就会调用 handleLocationUpdate。

locationManager,当 startUpdating 被调用时,会发送新的位置,一开始和移动时每秒发送很多次,直到设备静止并达到精度。 TTLlocationHandler 正在过滤这些事件,并且仅根据配置在需要时发送通知。

请注意,在 -(id)init 中,_recencyThreshold 设置为 60。因此我们每 60 秒保存或显示一个引脚。如果您想要更小的间隔,请更改此设置。

实际上,除非设备接通电源,否则 TTLocationHandler 将始终在后台切换到重要的位置更改。如果使用电池供电,您将不会获得那么小的更新间隔,但您会获得更新。

我添加了一个属性来配置连续后台更新而不收费。

TTLlocationHandler 的使用示例

我在存储库中添加了另一个类,以展示我将如何使用我的处理程序实现您的目标。我添加了 LMPinTracker 类,您可以在其中添加用于存储和上传位置的代码。

看看 LMAppDelegate.m
    self.pinTracker.uploadInterval = 30.00;

将其更改为您想要的上传到服务器之间的任何间隔。
    self.sharedLocationHandler.recencyThreshold = 5.0;

将 5.0 更改为您想要的存储位置之间的最短时间。它不会准确,会因行进速度和信号强度而异,但基本上,在 x 秒间隔后,它会考虑存储的位置过时并尝试获取另一个准确位置。

现在查看 LMPinTracker.m 文件
将您的数据存储代码放在这两行之后:
    // Store the location into your sqlite database here
    NSLog(@"Received location info: %@ \n Ready for store to database",lastKnowLocationInfo);

在此评论后将您的网络上传代码放在此处:
    // Do your upload to web operations here

评论

这应该做你想做的,同时仍然尊重用户电池和后台操作。

基本上,当用户正在旅行时,更新将按照您设置的间隔持续进行。
当用户处于静止状态时,将不会有任何更新和重要事件。
当没有新事件时,您也不会上传到网络。
当用户再次开始移动时,日志记录和更新将恢复。

如果我是你,想进一步完善它,我会考虑设置一个区域和时间来检查。如果用户在一段时间内保持静止,请仅切换到重要位置更新。然后您将关闭定位服务,但当用户再次开始时会重新启动。

关于iphone - 在没有 NSTimer 的情况下每隔几秒调用一次获取当前坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12841017/

相关文章:

ios - 如何通过发送产品名称来查找特定的产品 ID?

iphone - 触摸屏幕上的任意位置即可激活方法

ios - 集成适用于iPhone的Linphone

iphone - 在 iPhone 上以编程方式接听来电

ios - 2x 从 .xcassets 检索的图像有时会给出 1x

objective-c - Objective-C 中有类似 Java 枚举的东西吗?

ios - 我可以在 App Store 上发布比以前更低的版本吗?

iphone - 如何在iPhone应用程序中处理身份验证

ios - iOS-后退按钮IOS6 vs IOS7

iOS 约束导致 SIGABRT 错误