iOS re-check location on load from background

妖精的绣舞 提交于 2019-12-13 11:50:57

问题


I'm building an app which displays result data based on your current location.

At the moment, I'm using the viewDidLoad method of a UIViewController to start the CLLocationManager and getting the current location. Once I have the location that matches the accuracy I desire, I do a request to my web service to get the results and dump it into a UITableView.

My problem is that when you close the app (although it's still running in the background). If you were to drive to another town, re-open the app, the data doesn't get updated and continues to show the results from your old location.

Basically when the UIViewController loads from the background, I need to be able to check the users location, and if they have moved a significant distance, update the contents of my UITableView.

However, because the viewDidAppear of the UIViewController isn't triggered when you load the app from the background, I'm not sure which method I can use.

I am aware of the stopMonitoringSignificantLocationChanges method which wakes up your app when a new location is found. However, this seems a little OTT because I only need to know once the app has loaded.

Is there any alternative to using the stopMonitoringSignificantLocationChanges method?


回答1:


You could register to receive notifications from UIApplication in -viewDidLoad. You may be interested in UIApplicationDidBecomeActiveNotification. Registering for notifications is easy.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
}

In -viewDidLoad we add ourselves as an observer of the UIApplicationDidBecomeActiveNotification and specify a selector to be invoked when that particular notification is received.

- (void)applicationDidBecomeActive:(NSNotification *)notification
{
    // Kick off your CLLocationManager
    [self updateCurrentLocation];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}

Finally, remember to remove yourself as an observer for this notification when the view unloads. It's good practice to balance your addObserver/removeObserver calls to NSNotificationCenter in this way.




回答2:


You can register your view for notifications. For views that need to keep track of application state I use this handy superclass.

@implementation BackgroundAwareObject

-init
{
    if(self=[super init])
    {
        NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(notifyApplicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
        [center addObserver:self selector:@selector(notifyApplicationWillEnterForeground:) name: UIApplicationWillEnterForegroundNotification object:nil];
        [center addObserver:self selector:@selector(notifyApplicationDidFinishLaunching:) name: UIApplicationDidFinishLaunchingNotification object:nil];
        [center addObserver:self selector:@selector(notifyApplicationDidBecomeActive:) name: UIApplicationDidBecomeActiveNotification object:nil];
        [center addObserver:self selector:@selector(notifyApplicationWillResignActive:) name: UIApplicationWillResignActiveNotification object:nil];
        [center addObserver:self selector:@selector(notifyApplicationDidReceiveMemoryWarning:) name: UIApplicationDidReceiveMemoryWarningNotification object:nil];
        [center addObserver:self selector:@selector(notifyApplicationWillTerminate:) name: UIApplicationWillTerminateNotification object:nil];
    }
    return self;
}

-(void)notifyApplicationDidEnterBackground:(NSNotification*)n
{
    [self applicationDidEnterBackground:[UIApplication sharedApplication]];
}

-(void)notifyApplicationWillEnterForeground:(NSNotification*)n
{
    [self applicationWillEnterForeground:[UIApplication sharedApplication]];
}

-(void)notifyApplicationDidFinishLaunching:(NSNotification*)n
{
    [self application:[UIApplication sharedApplication] didFinishLaunchingWithOptions: [n userInfo]];
}

-(void)notifyApplicationDidBecomeActive:(NSNotification*)n
{
    [self applicationDidBecomeActive:[UIApplication sharedApplication]];
}

-(void)notifyApplicationWillResignActive:(NSNotification*)n
{
    [self applicationWillResignActive:[UIApplication sharedApplication]];
}

-(void)notifyApplicationDidReceiveMemoryWarning:(NSNotification*)n
{
    [self applicationDidReceiveMemoryWarning:[UIApplication sharedApplication]];
}

-(void)notifyApplicationWillTerminate:(NSNotification*)n
{
    [self applicationWillTerminate:[UIApplication sharedApplication]];
}

-(void)configurationChanged
{
    // User has update application configuration panel

}

- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{    
    // Override point for customization after application launch.  

}


- (void)applicationWillResignActive:(UIApplication *)application 
{
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}


- (void)applicationDidEnterBackground:(UIApplication *)application 
{
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
     */
    _background = YES;
}


- (void)applicationWillEnterForeground:(UIApplication *)application 
{
    /*
     Called as part of  transition from the background to the active state: here you can undo many of the changes made on entering the background.
     */
}


- (void)applicationDidBecomeActive:(UIApplication *)application 
{
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
    _background = NO;
}


/**
 applicationWillTerminate: saves changes in the application's managed object context before the application terminates.
 */
- (void)applicationWillTerminate:(UIApplication *)application
{
}

// try to clean up as much memory as possible. next step is to terminate app
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
    [super dealloc];
}

@end



回答3:


In your AppDelegate.m you must have this method predefined (as in the template you created initially when starting your project in Xcode) -

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
}

As the description says, this method is automatically invoked by iOS when the app is about to become active. Here you could get the latest location to do further processing.



来源:https://stackoverflow.com/questions/7407479/ios-re-check-location-on-load-from-background

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!