Invoke get current coordinates every few seconds without NSTimer

后端 未结 2 402
别跟我提以往
别跟我提以往 2021-01-15 03:45

I know how to make this with NSTimer but I wan\'t to get current iPhone coordinates without timer on every few seconds. I can\'t use timer because I am getting coordinates w

相关标签:
2条回答
  • 2021-01-15 04:23

    I have had issues with timers in the background state. There is no guarantee that you will have an active run loop and so the timer will never fire until you come back to foreground. What I did is:

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

    I do this on a background thread inside BackgroundIdentifierTask begin and end calls. I am not fully confident that I have it all correct, in fact I looked at your question to see if an answer may help me confirm or correct my understanding of the requirements.

    You also must have the background mode for location services enabled in your default info.pList if you want to continually monitor location. You do not need that if you are just using significantLocationUpdates or geofence.

    My timer does work and does fire as intended set up this way. It did not work reliably prior to that.

    Aside from that, you may be best off with no timer. Using your code above, just change the properties of your location manager. Desired accuracy and distance filter are properties that will reduce how often the manager sends out a new location notification.

    See an example of my own location handler I just posted on github for anyone that is interested:

    http://github.com/dsdavids/TTLocationHandler

    I don't think the timer is the key. If you drop the TTLocationHandler class in your project, then take a look at how the LMViewController class responds to the handler.

    NSNotificationCenter *defaultNotificatoinCenter = [NSNotificationCenter defaultCenter];
    [defaultNotificatoinCenter addObserver:self selector:@selector(handleLocationUpdate) name:LocationHandlerDidUpdateLocation object:nil];
    

    sets up the controller as an observer. Whenever the handler determines a new or more accurate location has been received, handleLocationUpdate is called.

    The locationManager, when startUpdating is invoked will send out new locations, many per second at first and when moving until the device is stationary and accuracy achieved. The TTLocationHandler is filtering these events and only sending notification as needed based on configuration.

    Note that in -(id)init, _recencyThreshold is set to 60. So we are saving or displaying a pin every 60 seconds. If you want smaller interval, change this.

    As it is, TTLocationHandler will always switch to significant location changes when in background unless the device is plugged in to power. You will not get that small an interval between updates if it is on battery power, but you will get updates.

    I added a property to configure for continuous background updates without charging.

    Example Use of TTLocationHandler

    I have added another class to the repository to show how I would go about achieving your goals with the my handler. I have added LMPinTracker class where you can add your code for storing and uploading the locations.

    Look at LMAppDelegate.m

        self.pinTracker.uploadInterval = 30.00;
    

    change that to whatever interval you want between uploads to the server.

        self.sharedLocationHandler.recencyThreshold = 5.0;
    

    Change that 5.0 to the minimum time you want between stored locations. It won't be exact, will vary on the rate of travel and the signal strength but basically, after x seconds interval it will consider the stored location stale and attempt to get another accurate location.

    Now look at the LMPinTracker.m file
    Put your data storing code right after these two lines:

        // Store the location into your sqlite database here
        NSLog(@"Received location info: %@ \n Ready for store to database",lastKnowLocationInfo);
    

    Put your web upload code right here after this comment:

        // Do your upload to web operations here
    

    Comments

    This should do what you are looking to do, while still respecting user battery and background operation.

    Basically, when a user is traveling, updates will be continuous at about the interval you have set.
    When a user is stationary, there will be no updates and no significant activity.
    When there is no new activity, you won't upload to web either.
    Logging and updating resumes when user starts moving again.

    If I were you, looking to refine it further, I would consider setting a region and time to check. If the user remains stationary for a length of time, switch to significantLocationUpdates only. Then you will power down the location services but be brought back up when the user gets underway once again.

    0 讨论(0)
  • 2021-01-15 04:27

    I think you can do it in background with a Timer:

    [NSTimer scheduledTimerWithTimeInterval:kAlertInterval target:self selector:@selector(checkLoc:) userInfo:nil repeats:YES];
    

    And in your method:

    - (void)checkLoc:(NSTimer *)timer {
        //...get your location and...
         if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
            //Do your background stuff
        }
    }
    

    I have this code working in some apps. Please, tell me if it works for you.

    0 讨论(0)
提交回复
热议问题