Selected map info selected from plist

I am trying to find specific details that the MapAnnotation

user clicks on. Details are retrieved from the file plist

. for this function i used - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view;

when using this. While I click on the specific annotation

one it fetches the location data from Map

as "Pune, Maharashtra, India @ <+18.50565666,+73.85559082> +/- 0.00m"

and does not check my plist values. Even after I gave these values ​​as attributes in the plist as a latlong for each location.can anyone solve my problem?

Details of my plist:

2013-02-18 12:16:56.039 MapView[9407:13d03] {
contents = "This Fish will be Found Rarely in South Asia";
imagesName = "kfish.jpg";
latlong = "Bangalore, Karnataka, India @ <+12.98333330,+77.58333330> +/- 0.00m";
listName = kFish;
location = "Bangalore, Karnataka, India";
}
2013-02-18 12:16:56.039 MapView[9407:13d03] {
contents = "This Fish will be Found Rarely in South Asia";
imagesName = "wallfish.png";
latlong = "Delhi, India @ <+28.59100531,+77.08826373> +/- 0.00m";
listName = WallFish;
location = "Delhi, India";
}
2013-02-18 12:16:56.039 MapView[9407:13d03] {
contents = "This Fish will be Found Rarely in South Asia";
imagesName = "fish.jpg";
latlong = "Chennai, Tamil Nadu, India @ <+13.07983465,+80.24625757> +/- 0.00m";
listName = Fish;
location = "Chennai,TamilNadu,India";
}

2013-02-18 12:16:56.039 MapView[9407:13d03] {
contents = "This Fish will be Found Rarely in South Asia";
imagesName = "bluefish.jpg";
latlong = "Mumbai, Maharashtra, India @ <+18.99460885,+72.82287598> +/- 0.00m";
listName = BlueFish;
location = "Mumbai, Maharashtra, India";
}

2013-02-18 12:16:56.040 MapView[9407:13d03] {
contents = "This Fish will be Found Rarely in South Asia";
imagesName = "Rarefish.jpg";
latlong = "Chennai, Tamil Nadu, India @ <+13.07983465,+80.24625757> +/- 0.00m";
listName = RareFish;
location = "Chennai,TamilNadu,India";
}

      

My coding:

- (void)geocodeRequest
{
CLGeocoder *geocoder = [[CLGeocoder alloc]init];
for (int i = 0; i < total; i++) {
    NSString *address = [allValues objectAtIndex:i] ;

            [geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
                        CLPlacemark *geocodedPlacemark = [placemarks objectAtIndex:0];
                        MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:geocodedPlacemark.location.coordinate addressDictionary:geocodedPlacemark.addressDictionary];

                        int zoomLevel=20;
                        MKCoordinateRegion region=MKCoordinateRegionMake(geocodedPlacemark.location.coordinate, MKCoordinateSpanMake(zoomLevel,zoomLevel));
                        [self.mapView addAnnotation:placemark];
                        [self.mapView setRegion:region animated:YES];
                        [self.mapView setZoomEnabled:YES];
                                  }];

}


-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
    total = self.arrayImages.count;
NSArray *newIndex = [mapView selectedAnnotations];
NSLog(@"sel :%@",newIndex);

    for (index = 0; index < total; index++) {
        dict = [self.arrayImages objectAtIndex:index];
        NSLog(@"%@",dict);

        if (latlong == newIndex) {

            CGRect rec = CGRectMake(0, 0, 250, 250);
            [self setView:[[[UIView alloc] initWithFrame:rec] autorelease]];
            [[self view] setBackgroundColor:[UIColor whiteColor]];
            UIImage *img = [UIImage imageNamed:[dict objectForKey:@"imagesName"]];

            UIImageView *im = [[UIImageView alloc] initWithImage:img];
            UILabel *lab1 = [[UILabel alloc] init];
            UITextView *detailsView = [[UITextView alloc] init];
            lab1.text = [NSString stringWithFormat:[dict objectForKey:@"listName"]];
            detailsView.text = [NSString stringWithFormat:[dict objectForKey:@"contents"]];
            detailsView.editable = NO;
            detailsView.bounds = CGRectMake(20, 20, 150, 150);
            detailsView.frame = CGRectMake(210, 720, 390, 350);
            detailsView.font = [UIFont systemFontOfSize:24];

            lab1.bounds = CGRectMake(20, 20, 150, 150);
            lab1.frame = CGRectMake(360, 600, 90, 50);
            lab1.font = [UIFont systemFontOfSize:24];
            im.bounds = CGRectMake(10, 10, 50, 50);
            im.frame = CGRectMake(200, 120, 370, 450);

        [UIView transitionWithView:[self view] duration:1.5
                           options:UIViewAnimationOptionTransitionCurlUp
                        animations:^ { [[self view] addSubview:im];
                                       [[self view] addSubview:lab1];
                                       [[self view] addSubview:detailsView];

         }completion:nil];
        }
    }


}

      

MapView Works fine.but when choosing a selected location only it doesn't work. Can anyone help me where I went wrong?

Thanks in advance.

+3


source to share


1 answer


In your method, didSelectAnnotationView

you seem to be iterating through yours arrayImages

, looking for the one with latlong == newIndex

. A few thoughts:

  • Using the equality operator ==

    to compare objects is usually not a sane technique. You have no assurances that the view annotation is the same object (if their properties were used copy

    , it would not be equal, since the address for your object and theirs may be different). And even if it did work, it's not a very reliable way to work.

  • I'm not really sure if I'll follow your logic anyway, even if the equality operator worked, because in geocodeRequest

    you create a new one MKPlacemark

    , from allValues

    , but in didSelectAnnotationView

    you are comparing it to arrayImages

    . And your operator if

    in didSelectAnnotationView

    looks at latlong

    and newIndex

    (the first thing I don't see is you set, the last one is an array of annotations). It just doesn't make sense to me. I don't see how they can match.

  • But these two previous points are irrelevant, because the correct solution is not to add yours MKPlacemark

    to your map and then loop over your list in didSelectAnnotationView

    to find a match, but instead create your own annotation class with all the properties you want. when the user enters the annotation. Or at the very least, have your own sub-annotation and define a property that you can use to find specific details from your array. Any approach works. But the key is not to try to iterate over your objects looking for a match, but to define a custom annotation that has everything you need to find it right away.

    For examples of custom annotation, see Define a custom annotation object in the location programming guide. Once you have defined your own annotation subclass with any additional properties you think you need, you then (a) modify geocodeRequest

    yours to instantiate your new annotation subclass, not MKPlacemark

    ; and (b) change yours didSelectAnnotationView

    to just fetch the required data from annotation

    (which is a property annotationView

    ). Thus, it completely eliminates the headache of iterating through the list of possible annotations in search of a match.

FYI, in another SO answer , I'll give some examples of options for handling callouts, popovers, etc., so maybe there is something that might be useful for you. I don't use special annotations there, but maybe it gives you some ideas about your integration with MapKit.


Let me illustrate this practice. Let's say that we want to annotate our map, but we want to keep track of additional properties. First, I define a custom annotation class that has my additional properties. (I'll subclass this from MKPointAnnotation

to make life a little easier for me.)

@interface CustomAnnotation : MKPointAnnotation

@property (nonatomic) NSUInteger index;
@property (strong, nonatomic) NSString *property1;
@property (strong, nonatomic) NSString *property2;
@property (strong, nonatomic) NSString *property3;

@end

      

Now when I want to add my annotations to my map view, I will use my own annotation class, making sure you set whatever properties I want. You can store the numeric index in your array, or store the actual properties you care about, or both:

CustomAnnotation *annotation = [[CustomAnnotation alloc] init];

// set the MKPointAnnotation standard properties

annotation.title = item.name;
annotation.coordinate = item.placemark.coordinate;

// set my custom properties

annotation.index = idx;
annotation.property1 = ...;
annotation.property2 = ...;
annotation.property3 = ...;

// now add the annotation to the map view

[annotations addObject:annotation];

      

Or, if you want to use all properties MKPlacemark

, you can do the following:



@interface CustomAnnotation : MKPlacemark

@property (strong, nonatomic) NSString *title; // MKPlacemark doesn't have title, so let add our own property for that
@property (nonatomic) NSUInteger index;
@property (strong, nonatomic) NSString *property1;
@property (strong, nonatomic) NSString *property2;
@property (strong, nonatomic) NSString *property3;

@end

      

And you will create the annotation as if you created MKPlacemark

but again set our custom properties:

CustomAnnotation *annotation = [[CustomAnnotation alloc] initWithPlacemark:item.placemark];

// set my custom properties

annotation.title = item.name;
annotation.index = idx;
annotation.property1 = ...;

[annotations addObject:annotation];

      

Now when I select the annotation, I can process accordingly:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    if ([view.annotation isKindOfClass:[CustomAnnotation class]])
    {
        CustomAnnotation *annotation = view.annotation;

        // note, I don't have to iterate through any arrays to figure out which
        // annotation I'm dealing with; I can just look at my custom properties

        NSLog(@"index = %d; property1 = %@", annotation.index, annotation.property1);

        // now do whatever you want with that annotation; I could look up the
        // annotations details by using the custom `index` property I defined,
        // or if I defined my annotations to store all of the detail properties
        // I needed, I can just access them directly
    }
}

      


In contrast to usage didSelectAnnotationView

, you can use a more standard behavior MKMapView

and show a standard callout bubble, set an accessory to the right of the callout, and then handle a click on that callout accessory:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if (![annotation isKindOfClass:[CustomAnnotation class]])
        return nil;

    MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
                                                                       reuseIdentifier:@"CustomAnnotationView"];
    annotationView.canShowCallout = YES;
    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

    return annotationView;
}

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    if (![view.annotation isKindOfClass:[CustomAnnotation class]])
        return;

    CustomAnnotation *annotation = view.annotation;

    // note, I don't have to iterate through any arrays to figure out which
    // annotation I'm dealing with; I can just look at my custom properties

    NSLog(@"index = %d; property1 = %@", annotation.index, annotation.property1);

    // now do whatever you want with that annotation; I could look up the
    // annotations details by using the custom `index` property I defined,
    // or if I defined my annotations to store all of the detail properties
    // I needed, I can just access them directly
}

      

+3


source







All Articles