HowTo initialise MKMapView with a given user location? - iphone

My app knows the current user position (CoreLocation.framework).
As soon as the user opens a new MapView his iPhone starts searching for the current position again.
Is it possible to skip that or to change the first user position for mkMapView?
Edit:
Is it possible to overwrite MKMapView and use an other LocationManager?

Yes, it is possible to have a separate location manager object and assign its value to the mapview (BTW, I'm using '=' below as list prefix to prevent the SO code-formatter from borking).
= In your UIViewController maintain two separate properties: one to a MKMapView and one to a CLLocationManager.
= Create a XIB file with the MKMapView and any other window chrome you want. Connect the outlets to the controller propeties. Make sure MKMapView does NOT follow user location.
= Have the UIViewController implement the CLLocationManagerDelegate protocol--especially the locationManager:didUpdateToLocation:fromLocation: method which will be called whenever a new location value is available. We'll be setting the controller as the delegate for the location manager.
= In the viewController's loadView method, load the NIB with the MKMapView in it. To give user feedback you may want to put up a UIActivityIndicatorView spinner and set it to startAnimating. Then you start with:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
self.locationManager.distanceFilter = 10; // or whatever
[self.locationManager startUpdatingLocation];
= In locationManager:didUpdateToLocation:fromLocation: check to see if the event was updated since the last N seconds. Then tell the location manager to stop updating, the spinner to stop animating, and get the lat/long data and assign it to the map view along with a view span and region so it zooms and centers to the right place.
= Now here's the tricky part: the blue marble 'throbber' is a feature of the mapview tracking user location. You'll have to momentarily 'fake it' until the real one kicks in (or just use a separate marker for the current location and maintain its position yourself). Personally I'd go with the blue marble that the user is familiar with.
= To make it so it shows right at startup you will need to create a custom MKAnnotationView with just the blue marble graphic added at the location returned by the location manager. This means taking a snapshot of a Mapview with the location showing, then photoshopping just the blue marble out and using it as the image for a custom annotation view.
= If you want it to actively follow the map, you can enable the userlocation tracking of the mapview and when it gets the actual data, you hide your previously set marker and let the mapview do the updating. The other option is to allow the existing location manager to continue receiving updates every second or so and update the position of the blue marble annotation yourself.
= To let the mapview's own userLocation do the updating add to viewDidLoad:
[self.map.userLocation addObserver:self
forKeyPath:#"location"
options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)
context:NULL];
self.map.showsUserLocation = YES; // starts updating user location
= Implement observeValueForKeyPath. It gets called when the location attribute of the mapview's userlocation has a value:
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([self.map isUserLocationVisible]) {
[self.locationManager stopUpdatingLocation];
self.ownBlueMarble.hidden = YES;
}
// The current location is in self.map.userLocation.coordinate
}
= To avoid the warm-up delay in showing current location, keep a reference to the viewController containing the map and the location manager so it doesn't go away (it's a bit of a memory hog but if you release it you'll have to wait again until MapView loads the tiles and is ready to go).
= In viewWillLoad you can stuff the last known location into the custom bluemarble annotation and show it. Toggle on/off the userLocation tracking and when you get the notification the same hide-the-annotation-show-the-real-marble trick will work. The mapview's own location manager kicks in and when it has the data, you can make your annotation marker disappear.
= You might want to implement the viewController's viewWillDisappear method and manually turn off userLocation tracking on the mapview so it's off by default the next time the view is brought up. You'll also want to get the last known userLocation and save it for the next get-go. That way, you can do all the positioning marker-juggling in the viewWillAppear method and not have to worry about userLocation interfering until you're ready for it.
Good luck.

In your controller:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
CLLocationCoordinate2D coord = {latitude: 37.423617, longitude: -122.220154};
MKCoordinateSpan span = {latitudeDelta: 1, longitudeDelta: 1};
MKCoordinateRegion region = {coord, span};
[mapView setRegion:region];
}
When map appears it's going to be centered close to Palo Alto

Try setting the showUserLocation property to false on initialisation and then restore the region the map view previously had (you will obviously have to store this before the previous map is destroyed).
Is this what you wanted?

You don't need to use another Location Manager, you can add whatever points you want to the map and update them via whatever other logic you want.
Let's say you had a socket connection to a remote control car, and that car send back socket data containing geo-location information in the payload. You could parse that out, and update the location of the thumbnail on your map in real time. The "userLocation" property is not needed for that, but you could show it if you wanted to.
The location of the user is read-only, you can use it or not. That doesn't mean you need another location manager to do anything you might need to do. It sounds like your app doesn't really need that feature, but I could be misunderstanding your question.

Related

How to add infoWindow to users current location in Google Maps v1.3 for iOS?

I would like to add an infoWindow when the user taps their current location (blue dot) in the Google Maps API V1.3 for iOS.
I can get infoWindows on other markers but not to display above the users location. Any help would be appreciated. Thanks!
As an alternative option, could you add a marker with a transparent icon at the user's current location?
You could use KVO to move the marker whenever the map view's myLocation value changes.
You can see some sample code for how to add an observer here (but instead of moving the camera, you could move your invisible marker):
about positioning myself,some problems
when you go with the the 'default' user location, you can't. Because it isn't a real marker, the callbacks aren't fired.
What I did in our case is that I set showsMyLocation=NO but I rolled my own location. I added another marker and used a CLLocationManager to position it according to THAT position..
So in pseudocode
- viewDidLoad
map.showsUserLocation=NO;
locationManager = [CLLocationManager new];
locationManager.delegate = self;
}
- locationManager:didUpdateUserLocation:newLoc {
if(!annotation) {
annotation = [GMSMarker new];
annotation.map = map;
}
annotation.position = newLoc;
}
=> own annotation that you can treat like any other marker!

Programmatically move the pin in digdog MapKitDragAndDrop framework

I have the digdog MapKitDragAndDrop in one my projects to achieve drag and drop pins. Im also allowing the user to search for location based on the address.
When the user searched and found his location coordinates, i want the pin to move to that location. Animation etc is not mandatory
I not able to figure out how to move the pin manually.
Just provide a new set of coordinates for your annotation, remove it and put it back in the map view's annotations. Some code from you would help be precise.
But basically the idea is that you remove the annotation from the map view and then put it back again, with the good coordinates. As a DDAnnotation is a MKPlacemark, that shouldn't be too hard.
It would look like:
- (void)annotation:(DDAnnotation*)annotation hasNewCoordinates:(CLLocation)location{
[_mapView removeAnnotation:annotation];
annotation._coordinate = location;
[_mapView addAnnotation: annotation];
}
Of course untested.

Move a pin according to the position of the user

In my iPhone application, I want to drop a pin at my current location using mapView and I also need to move another pin or a ball as my position changes. How can I do this?
To display user location, just add :
mapView.showsUserLocation = YES;
To get it, use the method userLocation which gives you a MKUserLocation.
You can then add a id<MKAnnotation> object with addAnnotation method to display another pin.

MKAnnotationView - Lock custom annotation view to pin on location updates

Update #5 I guess it's bounty time. 100+ views and no one's taken a stab, even with the code sample I've posted. How about some reputation points!
Update #4This is a pretty complicated question, so I created a new tab based project which just includes the parts of my app I'm having trouble with here. You can download it from: http://www.servinitup.net/CustomCalloutAnnotation.zip
Feel free to open it up (need to add your own bundle identifier to run it on your phone) and play around with it, and see if you can get that darned callout annotation to move with the pin!
Update #3 Tried making setAnnotation a public method of the tutorial's CalloutMapAnnotationView and calling that directly. Didn't have any luck. Despite little oddities that occurred, the only thing that moved was the little triangle portion of the callout. I could not get the entire callout to move.
Update #2 Still not much luck, but have now been looking for ways to programmatically create a "pinch to zoom" and then undo it immediately, so the user never sees a change. Hoping that doing this programmatically will have the same effect as doing it manually, and the callout annotation will pop back to it's parent. Any ideas?
Update #1 After playing around here's where I've gotten:
- replaced self.calloutAnnotation.coordinate = coords; with self.calloutAnnotation.latitude = coords.latitude;self.calloutAnnotation.longitude = coords.longitude;
- With that changed, if I slightly pinch the map to zoom in or out after the pin has been updated, the callout annotation animates to the correct position, right over the pin.
So now I need to figure out how to get this to happen without the user having to actually pinch to zoom.
Original Post
I, along with other SO users, are using this awesome solution to create a custom callout annotation:
http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/
When you use a standard callout (annotationview.canShowCallout = true) and the pin moves around the screen as the location is updated, the standard callout tracks right along with the pin, as if they're locked together.
When using the custom callout solution above, when my pin moves around after location updates, the callout annotation stays in it's original location. Of course, I'd like to mimic the iOS standard and have the custom callout annotation track along with the pin.
Here's the code I have so far, that's successfully moving the annotation view, but not the custom callout annotation view:
/* core location broadcasts a notification, and my view controller listens to that notification and calls locationManagerDidFindLocation */
- (void)locationManagerDidFindLocation:(NSNotification *)notif {
CLLocation *location = [notif.userInfo objectForKey:#"location"];
CLLocationCoordinate2D coords = [location coordinate];
MKCoordinateSpan span = MKCoordinateSpanMake((5/69), (5/69));
MKCoordinateRegion region = {coords, span};
// if we don't have a current location yet, create one, place it on the map, and adjust the map's region
// otherwise, update the annotation placement and map position in a smooth animation
if (self.currentLocationAnnotation == nil) {
self.currentLocationAnnotation = [[CurrentLocationAnnotation alloc] initWithCoordinate:coords andTitle:#"My Title" andSubtitle:#"My subtitle"];
[self.mapView addAnnotation:self.currentLocationAnnotation];
[self.mapView setRegion:region animated:true];
[self.mapView regionThatFits:region];
} else {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.45];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// this moves my annotation view perfectly
self.currentLocationAnnotation.coordinate = coords;
// ******* this is where my problem is
// ******* this custom callout annotation view stays
// ******* in it's original place, even though it's
// ******* parent annotation view is moving around the screen
self.calloutAnnotation.coordinate = coords;
[self.mapView setRegion:region animated:true];
[self.mapView regionThatFits:region];
[UIView commitAnimations];
}
}
I created a project based on your CalloutMapAnnotationView demonstrating a IB based solution. Arrow keys animate motion of the location annotation and it's callout annotation. The callout now also automatically resizes based on the supplied contentView, and the view is loaded from a separate nib. Good luck!
https://github.com/jacobjennings/JJMapCallout
I know you aren't going to like this answer, but it works. The sample you linked to just draws a custom image in the overlay through the most difficult way possible (drawRect:). Have you considered rendering your overlay once into a UIImage, and just setting the image property on a very simple MKAnnotationView? Even if you need to change the content periodically, like updating the number of friends at a bar, you can redraw the image when the change occurs and update the appropriate MKAnnotationView.
I review your code and my recommendation is to create a new custom MKAnnotationView and encapsulate on it both views (the pin and the callout).
But for your current code consider read the approved response this question: MKMapView moving Annotations Automatically - animate them?
Cheers.

How to find the current location of iphone and update it

I am new to iphone development.I am creating a map application. I have created tool bar with a button below the mapview.When i click the button it should display a alert view showing the current location and asking to update. on clicking OK in alert view should open my map with the current location and CANCEL to close the alert view.The button action is defined in the method
-(IBAction) gosearch : (id) sender{
NSLog(#"inside go search");
}
What should i do to achieve my task.I have added core location framework.But i dont know how to proceed.I saw some inbuilt methods to be used from this link http://iappdevs.blog.co.in/2008/12/06/get-current-location-sample-example-iphone-programming/ but i am not able to implement it.Please guide me.Thanks.
the MapKit component MKMapView display the current position on its own, you don't have to do anything.
Actually, internally, it instantiates a CLLocationManager and starts updating location on it to get live position events. when it gets those positions, it displays them as a blue dot, with circles with various radius to indicate the accuracy, but this is done automatically.
To trigger the display of the current position on the MKMapView, just set the showsUserLocation to YES on your MKMapView instance and you'll get this this blue dot being displayed and updated in real time.
Where does your problem start - have you got a core location delegate that gets location updates? You need to start core location using these methods:
In applicationdidfinishingLauncing()
{
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // Tells the location manager to send updates to this object
[locationManager startUpdatingLocation];
This will get core location to call you back as it gets updates on the location, starting with a rough location but further updates should get you a more accurate focus.