CLLocationManager with MKMapView avoiding multiple instances - ios

I have a question regarding how to properly set up my app to deal with multiple views needing location information. I have a two views. One a normal UIViewController that has a table view, the other, a UIViewController that houses an MKMapView. Now, both of these views need location information. As it stands, I have a singleton that implements a CLLocationManager to get all the user location information for the app. However, I was thinking about some other possibilities because sending a NSNotification every time the location is updated to change the center of my map seems like not the preferred approach as opposed to using the tracking methods in MKMapView. So, I am thinking about a couple options.
When the MKMapView appears, pause the singleton CLLocationManager and then, when it disappears start it up again. This way, only one location manager is updating at a time and I could still use the user tracking on the MKMapView. However, there will still be two objects that collect location data which seems like bad coding.
Use only the singleton CLLocationManager and update the center of the map based on that by posting notifications in the app.
As it stands, I am leaning toward option 1. However, I am very interested in what the preferred approach to a MKMapView and another view that needs location information in regards to how to update location throughout the app and was hoping someone could fill me in on what the proper approach would be. Thanks

Related

locationManager background battery life

I have a question about saving battery when using locationManager. I was looking here:
https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/LocationBestPractices.html
And here:
http://tumblr.twicetwice.net/post/47249353501/cllocationmanager-battery-saving-tips-and-best
And in many stackoverflow postings, but I can't use the most of these tips like startMonitoringSignificantLocationChanges(), because I need high accuracy updates very often, also in the background. Moreover I know that I can't use a timer in the background to get the location for example every 10 seconds. Now I want to stop getting location updates if I don't move for a specific time. And when I move again, I want to get updates again. I can't use
pausesLocationUpdatesAutomatically = true, because I don't want the user to put the app back into the foreground to update the location. Is there any other way to extend battery life when the app is in the background? I also searched for examples with CoreMotion, because I had the idea to turn off the GPS if I don’t move for a specific time and turn it on if the accelerometer detects a few steps. But I found out that this also doesn’t work in the background, or does anyone know a way to get this working? Are there maybe much better solutions for stop updating location when I don’t move and start updating location when I move while the app is in backgound? I would be thankful for any suggestions what I could do.
Btw: I’m pretty new in Swift so maybe there are very easy solutions that I don’t know and that I couldn't find.
Now I want to stop getting location updates if I don't move for a specific time. And when I move again, I want to get updates again
You might be describing Visit monitoring. — But in general, asking for high accuracy locations continuously is very battery-expensive; that is why you're not supposed to do it unless the device is hooked to a source of power.

Updating geofences with low accuracy in background, update position on map at high accuracy, does not work as intended

I'm writing an app which use the location for two purposes:
1) It shows the user's location on a map (with navigation-like accuracy) in a location manager instance and delegate, contained in a viewcontroller
2) In the background, even when closed, it gets the nearest 20 points of interest (list stored in userdefaults) and activates a geofence for these, so the user is noticed when getting nearby. This is done by lowest accuracy possible (3km) to save power, and set up in another location manager instance, initiated when the app is first opened.
The problem is, that the CLLocationmanager object seems to be static so when I call it from two different places, it's the same instance that's returned, and the accuracy, intervals etc, seems to be the same, since both delegates are called simultaneously all the time.
Therefore, the geofences setup method is called all the time, when the user just move a little bit, which I want the map to reflect.
Yes, there's only one location manager. So reconfigure it when you go into the background and when you come back into the foreground. It may be convenient to switch its delegate to another object at those times as well (so that each delegate object can focus on one problem).
the CLLocationmanager object seems to be static
Yup! CLLocationmanager object is a Singleton so different objects cannot be created. To Solve your problem you need check you application status, which can be done using :
[[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground
Once you know the application state you can configure CLLocationmanager's object properties accordingly. Hope it helps!

dynamic MKMap points loading

Im trying to find the best way to work with MKMaps with my needs.
My code is very long so ill just explain.
What do i need to do? (*)
understand what is the location that the user is interested in.
get points from the internet for this location.
load them into the map.
update the map (cluster annotations) with animation.
How do I do it now?
in regionDidChangeAnimated I call GetPoints.
GetPoints starts a NSURLConnection in order to get the points in the region (using region.span.latitudeDelta and region.span.longitudeDelta).
in connectionDidFinishLoading I'm calling AddPoints.
AddPoints is checking for every point if its already on the map, if not its added (not directly to the MapView but to a "hidden" AllPointsMap).
after adding all points into the AllPointsMap Im calling updateVisibleAnnotations.
updateVisibleAnnotations is updating the MapView (by separating the visibleMapRect to gridMapRects and shows only one MKAnnotation for each one) and takes care to animate the annotations in and out the way they should.
What is the problem?
it works! but its not so smooth, updateVisibleAnnotations takes a lot of time and the map is not responding in that time...
So I'm calling updateVisibleAnnotations in background, like that:
[self performSelectorInBackground:#selector(updateVisibleAnnotations) withObject:nil];
Its awesome, really smooth mapView animations, not disturbing user interface.
BUT from time to time i get "Collection <__NSArrayM: 0x76c11b0> was mutated while being enumerated".
I can't tell exactly what causing it. But my guess is that main thread is trying to add or remove annotations while background threads are using them.
I have tried using #synchronized in updateVisibleAnnotations so main thread is not interrupting background thread, but it remained the same.
I have tried using a self.waitinigForUpdate BOOL #property to indicate that updateVisibleAnnotations is running in background, still get the same error…
Makes me wonder: Maybe this is not the best way doing what I need to do (*), is it??

GPS Delegate Sending Information to CCLayer

I am currently trying to use a GPS delegate to get the user's GPS location and send that information to a CCLayer from Cocos2d. The idea is to display the GPS coordinates on screen using a CCLabelTTF. I would also like to be able to use the schedule function on a CCLayer to update the location.
The reason I have resorted to asking this question is because all of the tutorials I have found create a UIViewController integrated with the GPS manager, which does not fit what I have in mind.
No code to show here because anything I have created has become a jumbled mess.
Any help would be appreciated.
Thanks
I am not familiar with CCLayer etc. However, getting GPS updates, isn't that simply:
Instantiating a CLLocationManager object
Setting the manager's delegate to your own object where you handle GPS updates. I.e., you will have to implement the 'CLLocationManagerDelegate' protocol.
At least implement the locationManager:didUpdateLocations: method (you may need more).
Perhaps I missed the essence of your question?

Macro Recording in iOS

Is it possible to record set of touch events on iPhone and then playback?
I have searched alot but could not find any answer. if its possible, can anyone explain with an example.
I m not looking for testing purpose. Within my application, instead of creating animation, i just want to record set of events and then want to playback to explain the app flow to the users.
Regards.
Recording is pretty simple. Look at the various "Responding to Touch Events" and "Responding to Motion Events" methods on UIResponder. Just create your own UIView subclass (since UIView inherits from UIResponder) and keep a copy of the events passed into the relevant methods.
Playback is a bit more complicated; there's no way to make UITouch or UIEvent objects (so you can't make a fake event and pass it on to -[UIApplication sendEvent:]). But, there's nothing stopping you from manually parsing an array of Event objects and handling it on your own (aside from it being some kind of ugly code).
There's no built-in macro capability, but you could certainly build that ability into your application. You'll need to do more than just play back events, though. Touches aren't normally visible, but if you're trying to explain how to use your app to the user you'll probably want to have some sort of visual representation for the touches that trigger different responses similar to the way the iOS Simulator uses white dots to represent multiple touches when you hold down the option key.
Assuming that you can solve that problem, two strategies for easily recording user actions come to mind:
Use the Undo Manager: NSUndoManager is already set up to "record" undoable events. If you invest some time into making everything in your app undoable, you could (maybe) perform a set of actions, undo them all to move them to the redo stack, and then save the events in the redo stack as your script.
Use Accessibility: The Accessibility framework sends notifications whenever user interface elements are touched. Your app could use those notifications to create a playback script. You'll still need to write the code to play back the events in the script, though.
You could mirror your application with AirServer and use any screen capture software to make the video.

Resources