草庐IT

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

coder 2024-01-21 原文

我知道如何使用 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/

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

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  4. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  5. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. 没有类的 Ruby 方法? - 2

    大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow

  8. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  9. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  10. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

随机推荐