Search code examples
iosobjective-cxcodemkmapviewmkannotationview

When I click the Pin not get the correct data. Solution?


I have a problem when I click on a pin are not sent the correct data. From what I understand even though it has a NSUInteger, these are always changing. How can I fix?

The code is:

DisplayMap.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MapKit/MKAnnotation.h>
#import <Parse/Parse.h>

@interface DisplayMap : NSObject <MKAnnotation> 

@property (nonatomic, assign) CLLocationCoordinate2D coordinate; 
@property (nonatomic, copy) NSString *title; 
@property (nonatomic, copy) NSString *subtitle;
@property (nonatomic, copy) NSString *icon;


@property (nonatomic, strong) NSString *Telefono;
@property (nonatomic, strong) NSString *Email;
@property (nonatomic, strong) NSString *Sito;
@property (nonatomic, strong) NSString *TipologiaLocale;
@property (nonatomic, strong) NSString *Cucina;
@property (nonatomic, strong) NSString *Vegano;
@property (nonatomic, strong) NSString *Valutazione;
@property (nonatomic, strong) NSString *Latitudine;
@property (nonatomic, strong) NSString *Longitudine;
@property (nonatomic, strong) NSString *FaceB;
@property (nonatomic, strong) NSString *Twit;

@property (nonatomic, strong) PFFile *Anteprima1;
@property (nonatomic, strong) PFFile *Anteprima2;
@property (nonatomic, strong) PFFile *Anteprima3;

@end

DisplayMap.m

#import "DisplayMap.h"


@implementation DisplayMap

@synthesize coordinate;
@synthesize title;
@synthesize subtitle;
@synthesize icon;

@end

Alberghi.h

#import <UIKit/UIKit.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <MapKit/MapKit.h>
#import <Parse/Parse.h>

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

#import "Reachability.h"
#import "TestFlight.h"
#import "MBProgressHUD.h"
#import "DisplayMap.h"
#import "Recipe.h"
#import "DettagliAlberghi.h"

@interface Alberghi : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate> {

    MKMapView *_mapView;
}

@property (strong, nonatomic) IBOutlet CLLocationManager *locationManager;
@property (strong, nonatomic) IBOutlet CLGeocoder *geoCoder;

- (IBAction)TornaHome:(id)sender;

@end

Alberghi.m

#import "Alberghi.h"

@interface Alberghi ()

@end

@implementation Alberghi

@synthesize locationManager;
@synthesize geoCoder;

- (void)viewDidLoad {
    [super viewDidLoad];

        _mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 65, 320, 415)];
        [_mapView setDelegate:self];
        _mapView.layer.cornerRadius = 5;

        locationManager.delegate = self;
        self.locationManager = [[CLLocationManager alloc] init];

        if(IS_OS_8_OR_LATER) {

            [self.locationManager requestWhenInUseAuthorization];
            [self.locationManager requestAlwaysAuthorization];
        }

        [self.locationManager startUpdatingLocation];

        _mapView.showsUserLocation = NO;
        [_mapView setMapType:MKMapTypeStandard];
        [_mapView setZoomEnabled:YES];
        [_mapView setScrollEnabled:YES];
        [self.view addSubview:_mapView];


        PFQuery *query = [PFQuery queryWithClassName:@"Ristoranti"];

        [query orderByDescending:@"createdAt"];

        [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

            if (!error)
            {

                //NSLog(@"QUERY -----> :%@", objects);


                for(NSDictionary *note1 in objects) {
                    float realLatitude1 = [[note1 objectForKey:@"Latitudine"] floatValue];
                    float realLongitude1 = [[note1 objectForKey:@"Longitudine"] floatValue];

                    NSLog(@"(PARSE) Latitudine: %f", realLatitude1);
                    NSLog(@"(PARSE) Longitudine: %f", realLongitude1);

                    DisplayMap *displayMap = [[DisplayMap alloc] init];

                    CLLocationCoordinate2D theCoordinate;
                    theCoordinate.latitude = realLatitude1;
                    theCoordinate.longitude = realLongitude1;
                    displayMap.coordinate = theCoordinate;
                    displayMap.title = [note1 objectForKey:@"NomeLocale"];
                    displayMap.subtitle = [note1 objectForKey:@"Indirizzo"];
                    displayMap.icon = [note1 objectForKey:@"PinMappa"];
                    [_mapView setDelegate:self];
                    [_mapView addAnnotation:displayMap];
                }
            }
        }];
}

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

        return nil;
    }

    static NSString* AnnotationIdentifier = @"AnnotationIdentifier";

    MKAnnotationView *pinView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];

    if (pinView == nil)
    {
        pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];

    }
    pinView.canShowCallout = YES;
    pinView.annotation = annotation;

    DisplayMap *myAnn = (DisplayMap *)annotation;
    pinView.image = [UIImage imageNamed:myAnn.icon];



    // Create a UIButton object to add on the
    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [rightButton setTitle:annotation.title forState:UIControlStateNormal];
    [pinView setRightCalloutAccessoryView:rightButton];

    return pinView;
}

- (void)mapView:(MKMapView *)mapView
 annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {

    if ([(UIButton*)control buttonType] == UIButtonTypeDetailDisclosure)
    {
        [self performSegueWithIdentifier:@"Prova" sender:view];


    }
}

#pragma mark - mappa

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
    for (MKAnnotationView *annotationView in views) {

        if (annotationView.annotation == mapView.userLocation) {
            MKCoordinateSpan span = MKCoordinateSpanMake(1.4, 1.4);
            MKCoordinateRegion region = MKCoordinateRegionMake(mapView.userLocation.coordinate, span);
            [mapView setRegion:region animated:YES];
        }
    }
}

- (IBAction)TornaHome:(id)sender
{

    [self performSegueWithIdentifier:@"TornaHome" sender:self];
}



- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@"Prova"]) {



        MKAnnotationView *annotationView = sender;



        DettagliAlberghi *destViewController =(DettagliAlberghi *) segue.destinationViewController;

        DisplayMap *displayMap = (DisplayMap *)annotationView.annotation;

        NSLog(@"DisplayMap? %@", displayMap);


        NSLog(@"Dettagli Ristorante:\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@
        \n%@", displayMap.title, displayMap.subtitle, displayMap.Telefono, displayMap.Email, 
        displayMap.Sito, displayMap.TipologiaLocale, displayMap.Cucina, displayMap.Vegano, 
        displayMap.Valutazione, displayMap.Latitudine, displayMap.Longitudine, 
        displayMap.Anteprima1, displayMap.Anteprima2, displayMap.Anteprima3, displayMap.FaceB,
        displayMap.Twit);

        destViewController.recipe = displayMap;






        /*
        MKAnnotationView *annotationView = sender;

        NSLog(@"Esporto i dati: %@", annotationView);

        DettagliAlberghi *destViewController = segue.destinationViewController;

        DisplayMap *displayMap = [[DisplayMap alloc] init];

        displayMap.title = [sender objectForKey:@"NomeLocale"];
        displayMap.subtitle = [sender objectForKey:@"Indirizzo"];
        displayMap.icon = [sender objectForKey:@"PinMappa"];
        displayMap.Telefono = [sender objectForKey:@"Telefono"];
        displayMap.Email = [sender objectForKey:@"Email"];
        displayMap.Sito = [sender objectForKey:@"Sito"];
        displayMap.TipologiaLocale = [sender objectForKey:@"TipologiaLocale"];
        displayMap.Cucina = [sender objectForKey:@"Cucina"];
        displayMap.Vegano = [sender objectForKey:@"Vegano"];
        displayMap.Valutazione = [sender objectForKey:@"Valutazione"];
        displayMap.Latitudine = [sender objectForKey:@"Latitudine"];
        displayMap.Longitudine = [sender objectForKey:@"Longitudine"];
        displayMap.Anteprima1 = [sender objectForKey:@"Anteprima1"];
        displayMap.Anteprima2 = [sender objectForKey:@"Anteprima2"];
        displayMap.Anteprima3 = [sender objectForKey:@"Anteprima3"];
        displayMap.FaceB = [sender objectForKey:@"Facebook"];
        displayMap.Twit = [sender objectForKey:@"Twitter"];




        NSLog(@"Dettagli Ristorante: \n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@", displayMap.title, displayMap.subtitle, displayMap.Telefono, displayMap.Email, displayMap.Sito, displayMap.TipologiaLocale, displayMap.Cucina, displayMap.Vegano, displayMap.Valutazione, displayMap.Latitudine, displayMap.Longitudine, displayMap.Anteprima1, displayMap.Anteprima2, displayMap.Anteprima3, displayMap.FaceB, displayMap.Twit);




        destViewController.recipe = displayMap;
        */

    }
}

@end

When I click on the pin, the app crashes. I added an NSLog in PrepareToSegue and I noticed that all the fields to export in View next are empty, however, the data is read through PFQuery in viewDidLoad. What's wrong? When I click the pin does not export the data required?

2014-11-29 08:08:16.190 Veg[1083:8473] (PARSE) Latitudine: 45.435745
2014-11-29 08:08:16.190 Veg[1083:8473] (PARSE) Longitudine: 10.986951
2014-11-29 08:08:16.191 Veg[1083:8473] (PARSE) Latitudine: 45.441578
2014-11-29 08:08:16.191 Veg[1083:8473] (PARSE) Longitudine: 10.982130
2014-11-29 08:08:29.102 Veg[1083:8473] DisplayMap? <DisplayMap: 0x7f90335b71f0>
2014-11-29 08:08:29.102 Veg[1083:8473] Dettagli Ristorante: 
La Lanterna
Piazzetta Portichetti, 6 Verona
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
2014-11-29 08:08:29.301 Veg[1083:8473] Double Coord: 0.000000, 0.000000
2014-11-29 08:08:31.356 Veg[1083:8473] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

I can not understand how to order ... always in the same order every time you open the View are always changing position and consequently when I click on a Pin View opens me different and not the one you want. Solutions? Thanks in advance


Solution

  • Update, add this in your viewDidLoad (in ViewController):

                displayMap.icon = [note1 objectForKey:@"PinMappa"];
    
                // Add this
    
                displayMap.Telefono = [note1 objectForKey:@"Telefono"];
                displayMap.Email = [note1 objectForKey:@"Email"];
                displayMap.Sito = [note1 objectForKey:@"Sito"];
                displayMap.FaceB = [note1 objectForKey:@"Facebook"];
                displayMap.Twit = [note1 objectForKey:@"Twitter"];
                displayMap.Cucina = [note1 objectForKey:@"Cucina"];
                displayMap.TipologiaLocale = [note1 objectForKey:@"TipologiaLocale"];
                displayMap.Valutazione = [note1 objectForKey:@"Valutazione"];
                displayMap.Vegano = [note1 objectForKey:@"Vegano"];
    
                // End of adding
    
                [_mapView setDelegate:self];
    

    Hi I assume you are using ARC, I'm afraid you have copied your code from a very old font, In fact a couple of them. (On example you have three instances variable what's name is title, one for the Protocol, and a couple of them on created an other from the property, with wrong synthesised). And the dealloc method better don't speak. Well change your code to this: (Don´t worry It has the same variable you need (without duplicates).

    DispalyMap.h:

     #import <Foundation/Foundation.h>
     #import <MapKit/MapKit.h>
     #import <Parse/Parse.h>
    
     @interface DisplayMap : NSObject <MKAnnotation>
    
     @property (nonatomic, copy) NSString *icon;
    
    
    @property (nonatomic, strong) NSString *Telefono;
    @property (nonatomic, strong) NSString *Email;
    @property (nonatomic, strong) NSString *Sito;
    @property (nonatomic, strong) NSString *TipologiaLocale;
    @property (nonatomic, strong) NSString *Cucina;
    @property (nonatomic, strong) NSString *Vegano;
    @property (nonatomic, strong) NSString *Valutazione;
    @property (nonatomic, strong) NSString *Latitudine;
    @property (nonatomic, strong) NSString *Longitudine;
    @property (nonatomic, strong) NSString *FaceB;
    @property (nonatomic, strong) NSString *Twit;
    
    @property (nonatomic, strong) PFFile *Anteprima1;
    @property (nonatomic, strong) PFFile *Anteprima2;
    @property (nonatomic, strong) PFFile *Anteprima3;
    
    @end
    

    Display.m: (Only this)

    @implementation DisplayMap
    
    @synthesize coordinate = _coordinate;
    @synthesize title = _title;
    @synthesize subtitle = _subtitle;
    
    @end
    

    Well, I need to help you the crash message (because If with this change your App don't work, probably the mistake could be in the new view controller).

    // Old answer:

    I can't understand your code 100% because there are some code missing, but I think you made lot´s of thing you don't need. Try this methods, (Comment your current methods, and paste this).

     - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
    {
    if (![annotation isKindOfClass:[DisplayMap class]])
    {
    
        return nil;
    }
    
    static NSString* AnnotationIdentifier = @"AnnotationIdentifier";
    
    MKAnnotationView *pinView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
    
    if (pinView == nil)
    {
        pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
    
    }
        pinView.canShowCallout = YES;
        pinView.annotation = annotation;
    
    DisplayMap *myAnn = (DisplayMap *)annotation;
    pinView.image = [UIImage imageNamed:myAnn.icon];
    
    
    
    // Create a UIButton object to add on the
    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [rightButton setTitle:annotation.title forState:UIControlStateNormal];
    [pinView setRightCalloutAccessoryView:rightButton];
    
    return pinView;
    }
    
    
    
     - (void)mapView:(MKMapView *)mapView
    annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
    
     if ([(UIButton*)control buttonType] == UIButtonTypeDetailDisclosure)
     {
        [self performSegueWithIdentifier:@"Prova" sender:view];
    
    
    }
    }
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    
    if ([segue.identifier isEqualToString:@"Prova"]) {
    
        MKAnnotationView *annotationView = sender;
    
    
    
        DettagliAlberghi *destViewController =(DettagliAlberghi *) segue.destinationViewController;
    
        DisplayMap *displayMap = (DisplayMap *)annotationView.annotation;
    
    
    
        destViewController.recipe = displayMap;
    }
    }