Application doesn't launch with location key after a significant location change - iphone

My application uses the core location also after the application terminates with the method startMonitoringSignificantLocationChanges in CLLocationManager class.
My application launches with a location key in iOS 5 and 6 in the method:
- (BOOL) application:application didFinishLaunchingWithOptions:launchOptions;
in AppDelegate class and everything works well.
But in iOS-7 betas the application doesn't launch with a location key after a significant location change.
Has anybody encountered this problem?
I tried it on a simulator and in the device.
Thanks for the help.

I have the same problem in my app, when the app was terminated by user from app switcher.
But it does launch with location key if it was terminated by OS for low memory or other reason.
It is the expected result from iOS7 unfortunately. An official apple response I got from one of their evangelists:
If a user swipes up in the app switcher then the OS will not launch
the app unless explicitly told to do so by the user. So no, SLC will
not be launching the app, nor will silent notifications. The only
thing that will launch the app at that point is the user tapping the
icon. The intention here is that the user has expressed their choice
of not having that app running any more for any reason, so we honor
that. In this situation, there's really nothing that you can do. The
next time the user launches the app you can let them know that some of
the data may be missing, although you really cannot tell whether
there's missing data or not (i.e. you might have been killed by the OS
in the background and the user may not have moved thereby not
triggering any SLC notifications). My suggestion would be to gather
the data you can within the policies of the OS and if the user has
manually killed the app then respect that wish and don't do anything.
By all means, feel free to file a bug report if this change in
behavior winds up causing problems for you or (especially) confusion
for your users.
Attach link to Apple DEV forums:
https://devforums.apple.com/message/882691#882691

Related

Monitoring regions but location icon disappears when app is killed

I have a CLLocationManager contained in a singleton and I have added around a dozen regions to monitor. I am successfully notified of boundary crossings when the app is in the foreground/background. However, when I force quit the app, the location icon disappears and I am not getting any callbacks.
As far as I can see, this is intended functionality as of iOS7. Here is a reply I found to a similar question, in this case involving significant location change: https://devforums.apple.com/message/882691#882691:
If a user swipes up in the app switcher then the OS will not launch the app unless explicitly told to do so by the user. So no, SLC will not be launching the app, nor will silent notifications. The only thing that will launch the app at that point is the user tapping the icon. The intention here is that the user has expressed their choice of not having that app running any more for any reason, so we honor that.
In this situation, there's really nothing that you can do. The next time the user launches the app you can let them know that some of the data may be missing, although you really cannot tell whether there's missing data or not (i.e. you might have been killed by the OS in the background and the user may not have moved thereby not triggering any SLC notifications). My suggestion would be to gather the data you can within the policies of the OS and if the user has manually killed the app then respect that wish and don't do anything.
By all means, feel free to file a bug report if this change in behavior winds up causing problems for you or (especially) confusion for your users.

Bring my app to the foreground in Objective-C

My app has to run for a long time (also) in the background, due to Location Services.
When a certain condition is met the app has to move to the foreground.
I was able to run my app in the background and bring it to the front manually.
Reading up on this issue I got confused on how to move my app to the foreground by code.
It has to be in an if statement but what to do from here?
No do not think this is possible. You will be able to spawn a UILocalNotification to show application state to the user, but it is my understanding that iOS prevents you from making your app take focus.
you can't do that without user interaction. You can present a UILocalNotification
-- you can't even be sure iOS leaves it running though!
on a jailbroken phone I guess it is possible
This is clearly not possible, as it would be a mess if any app could just take over control at any point in time. As mentioned, you have to post a notification, and then it is up to the user if he or she wants to launch the app. If you notification states a good reason why they should launch your app, they might very well do it :-) And remember, don't mix up the user's needs with your/your app's needs.

App behaviour when an iOS device is restarted(with the app running)

I am facing a weird problem. My iPhone app is password protected and only after entering the correct password, can the user be logged in again. Also the app has multiple screens.
Suppose I am on a particular screen(after logging in) and switch off the device(with app still running), switch on the device back and launch my application, it starts back from the screen which was visible when the device was restarted. The password screen is not shown, and it seems like applicationDidFinishLaunching was never called. When I kill the app from background and start it again, it works normal.
Wouldn't the app loose all data in memory when the device is restarted? Wouldn't the views will have to be drawn again? How exactly does an app behave in this case.
EDIT:
I did what TriPhoenix has suggested. What I observed is that if you switch on the device and launch the application very soon, the applicationDidBecomeActive delegate method doesn't get called. However if you give it some time before launching, everything seems to work as expected. Isn't the applicationDidBecomeActive method supposed to be called with every app launch?
What I am testing on:
OS: iOS 5.0.1
Xcode: 4.2.1
Device: iPhone 4s
Is it possible that your app is very small in terms of memory usage? I remember a WWDC talk (cannot find the right one right now unfortunaly) where it is told that very small apps in terms of memory usage (a limit is not publicly defined but I think it was around 16 MiB memory usage) are not killed on low memory conditions but rather suspended to the phone's flash memory to be awakened later. I'm not sure if this is designed to survive a complete shutdown but it would sure be one of the few possibilities. To check this you could try to artificially increase your memory usage by creating some large objects / arrays and see if the problem disappears.
In any case there might be better functions to reactivate the password protection, e.g. applicationWillEnterForeground: or applicationDidBecomeActive: as this should cover all possibilities where the user might return to your app.

Xcode / iOS simulator: Trigger significant location change manually

Is there a way to manually tell the device to dispatch a significant location change notification that will wake up any applications registered for this notification?
This is for testing only, and I realize this private API call would get rejected upon submission to the app store.
So two answers:
A) Hop on a train :-)
B) Use the simulator. In iOS 5.x simulator, there is a debug menu that has a location submenu. Choose freeway drive. This will start the simulator on an imaginary journey down the scenic 280 in Northern California. It gives you everything but the view: your app will get Significant Location Change updates, and will also be launched in the background if it has been suspended.
To verify that you are actually moving, launch safari in the simulator, and go to maps.google.com and click the little track my location button. You should be moving.
Awesome! Now how to debug the lifecycle problem of being launched by the system? Easy! Have xCode wait for your app to be launched to start debugging. From the Scheme menu, choose edit scheme. In the Run Scheme, and the Info tab, for the "Launch" setting choose : "Wait for My.app to launch".
Run your app once in the simulator, so that it starts monitoring for location updates, then force quit it, so that it is suspended. Add a break point in your application did finish launching function, and wait. As soon as your simulator has gone far enough, your application will be woken up, your breakpoint hit, and you are in the money.
But really, the train ride is more fun.
Well, I've found that I can do this by toggling on and off Airplane mode and/or WiFi. Perhaps start the app with the device in airplane mode, then close the app and turn airplane mode off. That will turn the GPS on and force a location update to be dispatched.
I also wanted to test the relaunch of my terminated app which uses significant change monitoring. I wrote a piece of code so that it would display a local notification when it gets launched by a location key in the launch options dictionary.
I ran my app in the simulator. Then killed it from the multitasking bar. Then I set the location of the iOS simulator to a custom location. I quit the simulator and started it again. My app received the significant location update and showed the local notification.
I was struggling with the same issue, how to test 'startMonitoringSignificantLocationChanges' and check if my app is receiving location updates when suspended.
I couldn't manage to catch the execution on a breakpoint but I managed to see the results of my implementation working by sending the new location data to the server.
The whole flow:
- Implemented with 'startMonitoringSignificantLocationChanges' and an API call to my server to update the location latitude and longitude
- Set the location updates background mode capability to true
- Run the app so the location manager is initiated and the app is listening for location changes
- Force closed the app
- Set the debug->location on simulator to freeway drive
- Opened maps to see if the location is changing
- Waited on the server to see for location updates and was getting new results every about 3 minutes
However, I'm still not sure if this is fine enough on a real device.
I'm working on Xcode Version 6.0.1 (6A317); tested on Simulator iPhone 5s (8.0).
Adding to MagicSeth's answer, if you need to test this on a real device instead of a simulator, you can trigger a background launch with UIApplication.LaunchOptionsKey.location key by disabling and re-enabling Location Services in General > Privacy screen in the Settings app.
Depending on your scenario I would suggest two solutions:
Use a Timer or LocalNotification that periodically calls stopMonitoringSignificantLocationChanges followed by startMonitoringSignificantLocationChanges which should trigger a new location to be sent to your code (might be the same Location as before).
Build your own GPS Simulator that you start in debug builds and that will call the same delegate methods like CLLocationManager would do.
One thing I noticed in iOS 7 and Xcode 5.1.1 - If you are expecting SLC events to fire up your app into background mode, it may or may not hit the breakpoints you set. For me, sometimes the NSLog message are not even showing.
If that's the case for you, you can view NSLog outputs from the System Log. You can open the System Log from iOS Simulator's Debug menu.
In iOS 4, you can register for significant location changes. From the Apple docs: With this service, location updates are generated only when the user’s location changes significantly; thus, it is ideal for social applications or applications that provide the user with noncritical, location-relevant information. If the application is suspended when an update occurs, the system wakes it up in the background to handle the update. If the application starts this service and is then terminated, the system relaunches the application automatically when a new location becomes available. This service is available in iOS 4 and later, only on devices that contain a cellular radio.
See the Apple docs here and here.
Here is some example code to register for signification location updates:
- (void)startSignificantChangeUpdates {
// Create the location manager if it doesn't exist
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startMonitoringSignificantLocationChanges];
}
The docs say: if you leave this service running and your application is subsequently suspended or terminated, the service automatically wakes up your application when new location data arrives. At wake-up time, your application is put into the background and given a small amount of time to process the location data. Because your application is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your application may be terminated.
Freeway drive
// MARK: - MKMapViewDelegate
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
guard let location = userLocation.location else { return }
print(location.speed)
}
Well, this is not possible as the application scope is limited to its own space and such kind of notification cannot be generated with Apple Documented APIs list.
Of course.. if any undocumented API is used, application will get rejection from apple due to the use of undocumented/private API.

How to load the initial view every time an app launches?

I am fairly new to iphone app development. I am creating an app that has multiple views. Initially it starts with a view for authentication and then load views according to user interaction. When I build and run the app - the first time it shows the "Default.png" screen and then shows the first view where I do my authentication process (typing in userid,password and do a web service) and then after the credentials are verified it takes me to the next view. When I close the app at this state in the simulator and reopen it again, I am seeing the same state in which I closed my app. But here is what I want. When I relaunch the app I should be able to show the "DEfault.png" and screen and then show my initial authentication view. Can you please help me out on this ? Thanks
It sounds like the problem you are trying to solve is that your authenticated session may time out while the app is suspended and you need to log in again.
Although the proposed solution (setting UIApplicationExistsOnSuspend to true) would work I think you should consider a different approach.
Apple recommends that you do everything you can to make it look like the phone supports multitasking. That is why, by default, your app will suspend and resume instead of exit and relaunch. In your case, though, you may need to re-login to resume the session. I offer you a couple of alternate solutions:
Cache the credentials (ie username and password) and silently use them to resume the session when needed. If the back-end supports this.
Detect when the session has become stale and bring in a view to inform the user that the session has expired and ask them to log in again. This would also address the issue if the user keeps the app active past the timeout of the session.
Both of these approaches should improve perceived app performance and integrate better into the Apple usability guidelines.
That's because iOS 4 apps are supposed to support multitasking. You can change the app so it doesn't: In Info.plist, set UIApplicationExitsOnSuspend to true (i.e. <key> UIApplicationExitsOnSuspend</key><true/>) — make sure it's a boolean and not a string. Note that this will probably make startup slower, since the app has to be launched again.
The other way is to handle applicationDidEnterBackground: in your app delegate and do two things:
Reset your view hierarchy (you can do this on next launch, but doing it earlier might help to free more memory)
Show "Default.png" in a full-screen view — iOS takes a screenshot of your app after it's hidden which it uses to animate the app back in.