MKPointAnnotation: title always visible. Is it possible? - ios5

My code for adding a marker and title is this:
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = coord;
annotationPoint.title = currentTitle;
[mapView addAnnotation:annotationPoint];
Is it possible to show title on marker immediately after marker is shown and always visible ?
Thanks much

MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = coord;
annotationPoint.title = currentTitle;
[mapView addAnnotation:annotationPoint];
[mapView selectAnnotation:annotationPoint animated:NO];
OR
- (void)mapView:(MKMapView *)map didAddAnnotationViews:(NSArray *)views{
for (MKAnnotationView *av in views){
if ([av.annotation isKindOfClass:[MKPointAnnotation class]]){
[mapView selectAnnotation:av.annotation animated:NO];
break;
}
}
}

Related

show user location on a map and stop location

Here is my goal:
I have to show the user location with his address on a map every time he open the view that has the MapView and then stop location to save battery. So far i can do it, but if the user moves to another area and enter the view (after leave it) the location does not change.
Here is my code:
- (void)viewDidLoad
{
mapView.mapType = MKMapTypeStandard;
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated{
if(!self.locationManager){
self.locationManager = [[CLLocationManager alloc] init];
}
[self.locationManager startUpdatingLocation];
}
-(void)viewDidDisappear:(BOOL)animated{
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
MKCoordinateRegion viewRegion =
MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
[mapView setRegion:adjustedRegion animated:YES];
[manager stopUpdatingLocation];
MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc]
initWithCoordinate:newLocation.coordinate];
geocoder.delegate = self;
[geocoder start];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
MapLocation *annotation = [[MapLocation alloc] init];
annotation.streetAddress = placemark.thoroughfare;
annotation.city = placemark.locality;
annotation.state = placemark.administrativeArea;
annotation.zip = placemark.postalCode;
annotation.coordinate = geocoder.coordinate;
[mapView addAnnotation:annotation];
geocoder.delegate = nil;
}
- (void)openCallout:(id<MKAnnotation>)annotation {
[mapView selectAnnotation:annotation animated:YES];
}
- (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>) annotation {
static NSString *placemarkIdentifier = #"Map Location Identifier";
if ([annotation isKindOfClass:[MapLocation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[theMapView dequeueReusableAnnotationViewWithIdentifier:placemarkIdentifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:placemarkIdentifier];
}
else{
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"rescue"];
[self performSelector:#selector(openCallout:) withObject:annotation afterDelay:0.5];
return annotationView;
}
return nil;
}
I have a CLLocationManager on another view that get user location without a map (here the location is working just fine). If a start the location on that view and go back to the view with the map it's is updated. Why that?
Any ideias?
- (void)loadView {
MKMapView *mv = [[MKMapView alloc]init];
mapView.showsUserLocation=YES;
mv.delegate=self;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
[mapView setCenterCoordinate:mapView.userLocation.location.coordinate animated:YES];
mapView.showsUserLocation=NO;
}
well to display it on the map
MKMapView *mv = [[MKMapView alloc]init];
CLLocationCoordinate2D c = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude);
[mv setCenterCoordinate:c animated:YES];
and to stop updating
[locationManager stopUpdatingLocation];

Set up my MapView; how do I add more than one annotation?

I've created a MapView in my app that zooms into the user's current location, and it works perfectly. See my code below:
.h file
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
#end
.m file
- (void)viewDidLoad {
[super viewDidUnload];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
self.mapView.delegate = self;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"You Are Here";
point.subtitle = #"Your current location";
[self.mapView addAnnotation:point];
}
This code places an annotation where the user's current location is. However from here, I want to add multiple annotations (so that users can see key locations around them). What code do I need to add/change in order to do this?
Thanks.
This can be done many, many different ways. It depends on your data source and needs
Here's a way to add two
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"You Are Here";
point.subtitle = #"Your current location";
[self.mapView addAnnotation:point];
MKPointAnnotation *point2 = [[MKPointAnnotation alloc] init];
point2.coordinate = aDifferentCoordinate;
point2.title = #"You Are Here";
point2.subtitle = #"Your current location";
[self.mapView addAnnotation:point2];
Here's a way to add a thousand at the same point
int i;
for(i = 0; i < 1000; i++)
{
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"You Are Here";
point.subtitle = #"Your current location";
[self.mapView addAnnotation:point];
}

MapView annotations/pins in iPhone

In my viewDidLoad: method I have set the MapView like this so that if user has selected all the locations then it should show all the locations/pin views and if only one then only one pin view should be shown.
- (void)viewDidLoad{
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
if ([vehicleLabel.text isEqualToString:#"All Vehicles"]) {
MKCoordinateRegion region = {{0.0, 0.0},{0.0, 0.0}};
region.center.latitude = 41.01860;
region.center.longitude = 28.96470;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[mapView setRegion:region animated:YES];
[mapView setDelegate:self];
Annotations *ann = [[Annotations alloc] init];
ann.title = #"Vehicle A";
ann.subtitle = #"VG 1";
ann.coordinate = region.center;
[mapView addAnnotation:ann];
NSMutableArray* annotations=[[NSMutableArray alloc] init];
CLLocationCoordinate2D theCoordinate1;
theCoordinate1.latitude = 41.01760;
theCoordinate1.longitude = 30.96470;
CLLocationCoordinate2D theCoordinate2;
theCoordinate2.latitude = 41.01860;
theCoordinate2.longitude = 31.96470;
CLLocationCoordinate2D theCoordinate3;
theCoordinate3.latitude = 41.01360;
theCoordinate3.longitude = 25.96470;
CLLocationCoordinate2D theCoordinate4;
theCoordinate4.latitude = 41.01560;
theCoordinate4.longitude = 27.96470;
Annotations* myAnnotation1=[[Annotations alloc] init];
myAnnotation1.coordinate=theCoordinate1;
myAnnotation1.title=#"Vehicle B";
myAnnotation1.subtitle=#"Group 1";
Annotations* myAnnotation2=[[Annotations alloc] init];
myAnnotation2.coordinate=theCoordinate2;
myAnnotation2.title=#"Vehicle C";
myAnnotation2.subtitle=#"Group 1";
Annotations* myAnnotation3=[[Annotations alloc] init];
myAnnotation3.coordinate=theCoordinate3;
myAnnotation3.title=#"Vehicle D";
myAnnotation3.subtitle=#"Group 1";
Annotations* myAnnotation4=[[Annotations alloc] init];
myAnnotation4.coordinate=theCoordinate4;
myAnnotation4.title=#"Vehicle E";
myAnnotation4.subtitle=#" Group 1";
[mapView addAnnotation:myAnnotation1];
[mapView addAnnotation:myAnnotation2];
[mapView addAnnotation:myAnnotation3];
[mapView addAnnotation:myAnnotation4];
[annotations addObject:myAnnotation1];
[annotations addObject:myAnnotation2];
[annotations addObject:myAnnotation3];
[annotations addObject:myAnnotation4];
NSLog(#"Annotations: %d",[annotations count]);
}
else {
MKCoordinateRegion region = {{0.0, 0.0},{0.0, 0.0}};
region.center.latitude = 41.01860;
region.center.longitude = 28.96470;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[mapView setRegion:region animated:YES];
[mapView setDelegate:self];
Annotations *ann = [[Annotations alloc] init];
ann.title = #"Vehicle A";
ann.subtitle = #"VG 1";
ann.coordinate = region.center;
[mapView addAnnotation:ann];
}}
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation{
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"aPin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
} else {
}
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
return pinView;}
And in my PickerView didSelectRow method: I have implemented:
-(void)pickerView:(UIPickerView *)pickerViewG didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if (component == kGroupComponent) {
NSString *selectedState = [self.vehicleGroup objectAtIndex:row];
NSArray *array = [groupVehicles objectForKey:selectedState];
self.vehiclesList = array;
[vehiclePicker selectRow:0 inComponent:kListComponent animated:YES];
[vehiclePicker reloadComponent:kListComponent];
}
NSInteger groupRow = [vehiclePicker selectedRowInComponent:kGroupComponent];
NSInteger vehicleRow = [vehiclePicker selectedRowInComponent:kListComponent];
NSString *group = [self.groupOfVehicles objectAtIndex:groupRow];
NSString *vehicle = [self.listVehicles objectAtIndex:vehicleRow];
groupLabel.text = [[NSString alloc] initWithFormat: #"%#", group];
vehicleLabel.text = [[NSString alloc] initWithFormat: #"%#", vehicle];
valueForOtherView = vehicleLabel.text;}
Here what I want to know is that what if user selects a single vehicle from the picker view then all other pin views/ locations should be hidden/removed from the view and the only selected location/ pin view should be shown.
How can I do that in this picker view didSelectRow method: ?
What I'm doing in a case similar to yours, is:
1) remove first all the annotations
for (id <MKAnnotation> anAnnotation in [NSArray arrayWithArray:mapView_.annotations]) {
[mapView_ removeAnnotation:anAnnotation];
}
2) and then paint the ones selected:
[mapView_ addAnnotation:myAnnotation];

impossible to show 2 colors in mapkit

ok desperation. This is killing me.. I totally do not understand MapKit at all.. Despite reading so many tutorial.. =(
For more information, I have 2 annotation classes - MyAnnotation and MyAnnotation2, it doesnt seems to work too.. Somebody plz help.. I am afraid I have no hair left soon =(
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
_annotations = [[NSMutableArray alloc] init];
_annotation2 = [[NSMutableArray alloc] init];
CLLocation *userLoc = _mapView.userLocation.location;
CLLocationCoordinate2D userCoordinate = userLoc.coordinate;
NSLog(#"user latitude = %f",userCoordinate.latitude);
NSLog(#"user longitude = %f",userCoordinate.longitude);
_listOfPolyClinics = [[NSMutableArray alloc] init];
_listOfPatients = [[NSMutableArray alloc] init ];
for (PolyClinics *polyclinics in [[PatientDatabase database]
polyClinics]){
[_listOfPolyClinics addObject:polyclinics];
}
NSLog(#"%i", [_listOfPolyClinics count]);
for (PatientDetails *patientDetails in [[PatientDatabase database]
patientCategoryList:_category]){
[_listOfPatients addObject:patientDetails];
}
NSLog(#"%i", [_listOfPatients count]);
for (PolyClinics *polyclinics in _listOfPolyClinics){
MyAnnotation * myAnnotation =[[MyAnnotation alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.longitude = polyclinics.longtitude;
theCoordinate.latitude = polyclinics.latitude;
myAnnotation.pinColor = MKPinAnnotationColorPurple;
myAnnotation.coordinate = theCoordinate;
myAnnotation.title = polyclinics.name;
myAnnotation.subtitle = [NSString stringWithFormat:#"%i",polyclinics.telephone];
//myAnnotation.annotationsPatients =
[_mapView addAnnotation:myAnnotation];
[_annotation2 addObject:myAnnotation];
}
for(PatientDetails *patientDetails in _listOfPatients){
MyAnnotation2 * myAnnotation =[[MyAnnotation2 alloc] init];
CLLocationCoordinate2D theCoordinate;
theCoordinate.longitude = patientDetails.longitude;
theCoordinate.latitude = patientDetails.latitude;
myAnnotation.pinColor = MKPinAnnotationColorGreen;
myAnnotation.coordinate = theCoordinate;
myAnnotation.title = patientDetails.nric;
myAnnotation.subtitle = [NSString stringWithFormat:#"%i",patientDetails.category];
[_mapView addAnnotation:myAnnotation];
[_annotation2 addObject:myAnnotation];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"%i", [_annotation2 count]);
MKPinAnnotationView *pinView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:[annotation title]];
for(id <MKAnnotation> a in _annotation2){
if([a isKindOfClass:[MyAnnotation class]]){
pinView.pinColor = MKPinAnnotationColorPurple;
}
else{
pinView.pinColor = MKPinAnnotationColorGreen;
}
pinView.animatesDrop=NO;
pinView.canShowCallout=YES;
return [pinView autorelease];
}
return pinView;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
is called every time the MKMapView needs to show a view for an annotation, it passes you that annotation for a reason. So instead of iterating through them and returning only the color for the first one in your array (you need to understand that returning from a function/method doesn't let the loop iterate more), use the parameter instead.
Also a good practice is to use
- (MKAnnotationView *)dequeueReusableAnnotationViewWithIdentifier:(NSString *)identifier;
so the AnnotationViews don't get created again from scratch, especially memory-wise!
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
BOOL isGreen = YES;
if([annotation isKindOfClass:[MyAnnotation class]])
isGreen = NO;
MKPinAnnotationView *pinView = nil;
if (isGreen) {
static NSString *greenPin = #"greenPin";
pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:greenPin];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:greenPin] autorelease];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
pinView.annotation = annotation;
}
else {
static NSString *purplePin = #"purplePin";
pinView = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier:purplePin];
if (!pinView) {
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:purplePin] autorelease];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
pinView.annotation = annotation;
}
return pinView;
}

MapKit How to pass managedObject from mapView to mapDetailView

I am trying to pass a managedObject from a mapView with multiple annotation to a mapDetailView with only one annotation of the managedObject passed. This works great in a tableView to mapDetaiView. Any help would be appreciated. My code ...
- (void)viewDidLoad {
[super viewDidLoad];
if (self.managedObjectContext == nil) {
self.managedObjectContext = [(CrossroadsTreasuresAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
// setup the mapView
[mapView removeAnnotations:mapView.annotations];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
[self.view insertSubview:mapView atIndex:0];
[mapView setDelegate:self];
// setup the location coordnates to Victoria, TX
double lat = [#"28.825" doubleValue];
double lng = [#"-97.009" doubleValue];
CLLocationCoordinate2D rcoord;
rcoord.latitude = lat;
rcoord.longitude = lng;
// setup the map region
//MapLocation *annotation = [[MapLocation alloc] init];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(rcoord, 25000, 25000);
MKCoordinateRegion adjustRegion = [mapView regionThatFits:region];
[mapView setRegion:adjustRegion animated:YES];
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"GarageSaleItem" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSArray *markerObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
for (int i = 0; i < [markerObjects count]; i++) {
NSDictionary *marker = (NSDictionary *)[markerObjects objectAtIndex:i];
// Set the annotation coordnates
double lat = [[marker valueForKey:#"latitude"] doubleValue];
double lng = [[marker valueForKey:#"longitude"] doubleValue];
CLLocationCoordinate2D coord;
coord.longitude = lng;
coord.latitude = lat;
// Create the annotation instatnce
MapLocation *annotation = [[MapLocation alloc] init];
// Set the annotation display information
annotation.coordinate = coord;
annotation.streetAddress = [marker valueForKey:#"streetAddress"];
annotation.city = [marker valueForKey:#"city"];
annotation.state = [marker valueForKey:#"state"];
annotation.zipCode = [marker valueForKey:#"zipCode"];
// Add the annotation the the map
[self.mapView addAnnotation:annotation];
[annotation release];
}
[fetchRequest release];
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// handle our two custom annotations
//
if ([annotation isKindOfClass:[MapLocation class]]) {
// try to dequeue an existing pin view first
static NSString* AnnotationIdentifier = #"com.coastalbendmedia.pin";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView) {
// if an existing pin view was not available, create one
MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
customPinView.pinColor = MKPinAnnotationColorPurple;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
// add a detail disclosure button to the callout which will open a new view controller page
//
// note: you can assign a specific call out accessory view, or as MKMapViewDelegate you can implement:
// - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
//
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control; {
DetailViewController *controller = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:controller animated:YES];
// Set the detail item in the detail view controller.
// THIS IS WHERE MY PROBLEM IS! indexPath Undeclared
NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
controller.detailItem = selectedObject;
[controller release];
}
indexPath is undeclared because you're not implementing a UITableViewDataSource method in this case! I don't know what you're trying to accomplish here, but I think that there could be more than one possible solution. First, you could try to add an object property to your annotation, and use that to get the corresponding NSManagedObject from the annotation. Second, you could use an NSMutableDictionary to store the objects instead of an NSArray. You would use it as follows:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for(NSManagedObject *object in markerObjects) {
// Create the annotation
MapLocation *annotation = [[MapLocation alloc] init];
[dictionary setObject:object forKey:annotation]
}
Then you would retrieve the corresponding object for an annotation like this:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSManagedObject *object = [dictionary objectForKey:view.annotation];
// Do whatever you want with your object
}
Please note that MapLocation here must conform to the NSCopying protocol since it is copied by the setObject:forKey: method.
Third, you could add all the informations (address, city, state, etc.) to your NSManagedObject subclass that conforms to the MKAnnotation protocol, and you won't have anymore the problem of retreiving an annotation corresponding to an object, since that would be the same.