override MKPointAnnotation class [closed] - ios

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I override MKAnnotation and add two property (NSManagedObject and UIImage) to MKAnnotation class something like that but it's not work what is wrong with this code?
// myAnnotation.h
#import <MapKit/MapKit.h>
#interface myAnnotation : NSObject<MKAnnotation>{
NSManagedObject *Contact;
UIImage *image;
NSString *title;
NSString *subtitle;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic,copy) NSManagedObject *Contact;
#property (nonatomic, copy) UIImage *image;
#property (nonatomic,assign) CLLocationCoordinate2D coordinate;
#property (nonatomic,copy) NSString *title;
#property (nonatomic,copy) NSString *subtitle;
#end
// myAnnotation.m
#import "myAnnotation.h"
#implementation myAnnotation
#synthesize Contact,title,subtitle,coordinate,image;
#end
// MapVC.h
#import "myAnnotation.h"
#interface MapVC : UIViewController<MKMapViewDelegate,UIActionSheetDelegate,MFMessageComposeViewControllerDelegate,MFMailComposeViewControllerDelegate,UISearchBarDelegate>{
MKMapView *mapview;
myAnnotation *tmpContact;
}
// MapVC.m
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[mapview removeAnnotations:mapview.annotations];
//add each object in Contacts entity to map view
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest=[[NSFetchRequest alloc]initWithEntityName:#"Contacts"];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)]];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:nil];
for (NSManagedObject *info in fetchedObjects) {
NSLog(#"Name: %#", [info valueForKey:#"name"]);
//initializetion latitude and longitude
aLng=[[info valueForKey:#"lng"] doubleValue];
aLat=[[info valueForKey:#"lat"] doubleValue];
//if latitude and longitude not null
if(aLng && aLat && aLng!=0.0 &&aLat!=0.0)
{
//create a new Coordinate
CLLocationCoordinate2D wimLocation;
wimLocation.latitude=aLat;
wimLocation.longitude=aLng;
myAnnotation *myAnn=[myAnnotation alloc];
myAnn.coordinate=wimLocation;
myAnn.title=[info valueForKey:#"name"];
myAnn.Contact=info;
UIImage *image = [UIImage imageWithData:[info valueForKey:#"photo"]];
myAnn.image=image;
//add create Annotation to mapview
[self.mapview addAnnotation:myAnn];
}
}
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[myAnnotation class]])
{
static NSString *reuseId = #"ann";
MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (av == nil)
{
av = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
}
else
{
av.annotation = annotation;
}
myAnnotation *ann = (myAnnotation *)annotation;
av.image = ann.image;
return av;
}
//return nil (default view) if annotation is not our custom type
return nil;
}

Just subclass MKPointAnnotation or implement the MKAnnotation protocol in your custom class.

Related

Show MapPin title on user tap

I have made a MapPin class like this
//.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
AND
.m
#import "MapPin.h"
#implementation MapPin
#synthesize coordinate,title,subtitle;
#end
And then in the cellForRowAtIndexPath of my class, I have
MapPin *ann = [[MapPin alloc] init];
ann.title = #"HERE";
ann.subtitle = #"Test";
ann.coordinate = region.center;
[riCell.mapView addAnnotation:ann];
And when the user taps on it I want the title and subtitle to show? Is there a method like on MapPin tap? I though it was supposed to occur automoactilly?
How can I show it on the user tap?
Thanks
You can use CLGeocoder delegate method and use CLPlacemark object and get the locality and distribute to the annotation accordingly
// get the place details from the current location
[geocoder reverseGeocodeLocation:self.locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error){
NSLog(#"Geocode failed with error: %#", error);
return;
}
// get all the details of the current location
placemark = [placemarks objectAtIndex:0];
// set the place details to the annotation
annotation.title = [NSString stringWithString:_placemark.subLocality];
annotation.subtitle = [NSString stringWithString:_placemark.locality];
[self.mapView addAnnotation:annot];
}];
}
This is Swift code ... same you need to implement in Objective C
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
/*
For now, all we have are some quick and dirty pins for viewing debug
annotations. To learn more about showing annotations,
see "Annotating Maps".
*/
if (annotation.title! == "red") {
let pinView = MKPinAnnotationView()
if #available(iOS 9.0, *) {
pinView.pinTintColor = UIColor.redColor()
} else {
pinView.pinColor = MKPinAnnotationColor.Red
}
pinView.canShowCallout = true
pinView.draggable = true
return pinView
}
canShowCallout = true is the Key here

How to find road distance between two Coordinates and make a polyline between same points?

I want to find road distance between two coordinates. Firstly i am taking source and destination from user and then using googleMap api i find the coordinates.
I am able to find coordinates and air distance but i am unable to find road distance and draw a polyline between them. Every method available on google is for older xcode and not supported on xcode 6.
Method i am using for finding coordinates
-(CLLocationCoordinate2D)FindCoordinates:(NSString *)place
{
NSString *addresss = place;
NSString *esc_addr = [addresss stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
NSString *req = [NSString stringWithFormat: #"http://maps.google.com/maps/api/geocode/json?sensor=false&address=%#", esc_addr];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:req]];
NSDictionary *googleResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *resultsDict = [googleResponse valueForKey: #"results"]; // get the results dictionary
NSDictionary *geometryDict = [ resultsDict valueForKey: #"geometry"]; // geometry dictionary within the results dictionary
NSDictionary *locationDict = [ geometryDict valueForKey: #"location"]; // location dictionary within the geometry dictionary
// nslo (#”– returning latitude & longitude from google –”);
NSArray *latArray = [locationDict valueForKey: #"lat"]; NSString *latString = [latArray lastObject]; // (one element) array entries provided by the json parser
NSArray *lngArray = [locationDict valueForKey: #"lng"]; NSString *lngString = [lngArray lastObject]; // (one element) array entries provided by the json parser
myLocation.latitude = [latString doubleValue]; // the json parser uses NSArrays which don’t support “doubleValue”
myLocation.longitude = [lngString doubleValue];
return myLocation;
}
method i am using for finding distance
-(IBAction)getLocation:(id)sender
{
sourceLocation = [self FindCoordinates:source1.text];
NSLog(#"%#",[NSString stringWithFormat:#"Source lat:%f Source lon:%f",sourceLocation.latitude,sourceLocation.longitude]);
destinationLocation = [self getMe:destination1.text];
NSLog(#"%#",[NSString stringWithFormat:#"Desti lat:%f Desti lon:%f",destinationLocation.latitude,destinationLocation.longitude]);
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:sourceLocation.latitude longitude:sourceLocation.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:destinationLocation.latitude longitude:destinationLocation.longitude];
CLLocationDistance distance = [loc1 distanceFromLocation:loc2];
NSLog(#"%#",[NSString stringWithFormat:#"Distance iin KMeteres %f",distance/1000]); // Gives me air distance
MKPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(37.776142, -122.424774) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil] ]; // Not able to modify these cordinates
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
[srcMapItem setName:#""];
MKPlacemark *destination = [[MKPlacemark alloc]initWithCoordinate:CLLocationCoordinate2DMake(37.73787, -122.373962) addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil] ];
MKMapItem *distMapItem = [[MKMapItem alloc]initWithPlacemark:destination];
[distMapItem setName:#""];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
[request setSource:srcMapItem];
[request setDestination:distMapItem];
[request setTransportType:MKDirectionsTransportTypeWalking];
MKDirections *direction = [[MKDirections alloc]initWithRequest:request];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
NSLog(#"response = %#",response);
NSArray *arrRoutes = [response routes];
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[map addOverlay:line];
NSLog(#"Rout Name : %#",rout.name);
NSLog(#"Total Distance (in Meters) :%f",rout.distance);
NSArray *steps = [rout steps];
NSLog(#"Total Steps : %lu",(unsigned long)[steps count]);
[steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Rout Instruction : %#",[obj instructions]);
NSLog(#"Rout Distance : %f",[obj distance]);
}];
}];
}];
}
How can draw a polyline also.
You have to use MKPolylineRenderer for iOS 8
Following is the code for adding MKPolyline by tapping on locations may you get help.
Pin.h
#import <Foundation/Foundation.h>
#import MapKit;
#interface Pin : NSObject <MKAnnotation>
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
- (id)initWithCoordinate:(CLLocationCoordinate2D)newCoordinate;
#end
Pin.m
#import "Pin.h"
#implementation Pin
- (id)initWithCoordinate:(CLLocationCoordinate2D)newCoordinate {
self = [super init];
if (self) {
_coordinate = newCoordinate;
_title = #"Hello";
_subtitle = #"Are you still there?";
}
return self;
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import MapKit;
#interface ViewController : UIViewController <MKMapViewDelegate>
#end
ViewController.m
#import "ViewController.h"
#import "Pin.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#property (nonatomic, strong) NSMutableArray *allPins;
#property (nonatomic, strong) MKPolylineRenderer *lineView;
#property (nonatomic, strong) MKPolyline *polyline;
- (IBAction)drawLines:(id)sender;
- (IBAction)undoLastPin:(id)sender;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.allPins = [[NSMutableArray alloc]init];
// add a long press gesture
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(addPin:)];
recognizer.minimumPressDuration = 0.5;
[self.mapView addGestureRecognizer:recognizer];
}
// let the user add their own pins
- (void)addPin:(UIGestureRecognizer *)recognizer {
if (recognizer.state != UIGestureRecognizerStateBegan) {
return;
}
// convert touched position to map coordinate
CGPoint userTouch = [recognizer locationInView:self.mapView];
CLLocationCoordinate2D mapPoint = [self.mapView convertPoint:userTouch toCoordinateFromView:self.mapView];
// and add it to our view and our array
Pin *newPin = [[Pin alloc]initWithCoordinate:mapPoint];
[self.mapView addAnnotation:newPin];
[self.allPins addObject:newPin];
[self drawLines:self];
}
- (IBAction)drawLines:(id)sender {
// HACK: for some reason this only updates the map view every other time
// and because life is too frigging short, let's just call it TWICE
[self drawLineSubroutine];
[self drawLineSubroutine];
}
- (IBAction)undoLastPin:(id)sender {
// grab the last Pin and remove it from our map view
Pin *latestPin = [self.allPins lastObject];
[self.mapView removeAnnotation:latestPin];
[self.allPins removeLastObject];
// redraw the polyline
[self drawLines:self];
}
- (void)drawLineSubroutine {
// remove polyline if one exists
[self.mapView removeOverlay:self.polyline];
// create an array of coordinates from allPins
CLLocationCoordinate2D coordinates[self.allPins.count];
int i = 0;
for (Pin *currentPin in self.allPins) {
coordinates[i] = currentPin.coordinate;
i++;
}
// create a polyline with all cooridnates
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coordinates count:self.allPins.count];
[self.mapView addOverlay:polyline];
self.polyline = polyline;
// create an MKPolylineView and add it to the map view
self.lineView = [[MKPolylineRenderer alloc]initWithPolyline:self.polyline];
self.lineView.strokeColor = [UIColor redColor];
self.lineView.lineWidth = 5;
// for a laugh: how many polylines are we drawing here?
self.title = [[NSString alloc]initWithFormat:#"%lu", (unsigned long)self.mapView.overlays.count];
}
- (MKPolylineRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
return self.lineView;
}
#end
Get distance by
CLLocationDistance dist = [from distanceFromLocation:current];

Custom MKAnnotationView Showing Wrong Image

I have an MKMapView where I want to display annotations of contacts' faces. I looked at Apple's sample app MapCallouts and have so far written this:
Annotation.h
#interface Annotation : NSObject <MKAnnotation>
#property (nonatomic, strong) UIImage *image;
#property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
+ (MKAnnotationView *)createViewAnnotationForMapView:(MKMapView *)mapView annotation:(id <MKAnnotation>)annotation;
#end
Annotation.m
#import "CustomAnnotationView.h"
#implementation Annotation
+ (MKAnnotationView *)createViewAnnotationForMapView:(MKMapView *)mapView annotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *returnedAnnotationView =
(CustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"Annotation"];
if (returnedAnnotationView == nil)
{
returnedAnnotationView =
[[CustomAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"Annotation"];
}
return returnedAnnotationView;
}
#end
CustomAnnotationView.h
#interface CustomAnnotationView : MKAnnotationView
CustomAnnotationView.m
- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithAnnotation:annotation reuseIdentifier:#"Annotation"];
if (self != nil)
{
Annotation *mapItem = (Annotation *)self.annotation;
// Create imageView and labels, etc.
}
return self;
}
Then, to drop my annotation, I have this method which loops through an array of contacts, gets their address, finds the CLLOcationCoordinate2D, and creates an Annotation.
-(void)sortContacts{
for (APContact *contact in self.peopleArray){
[operationQueue addOperationWithBlock:^{
NSString *addressString = // get address from contact;
contact.addressString = addressString;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:addressString
completionHandler:^(NSArray* placemarks, NSError* error){
if (placemarks && placemarks.count > 0 && !error) {
CLPlacemark *topResult = [placemarks objectAtIndex:0];
CLLocation *location = topResult.location;
CLLocationCoordinate2D coordinate = location.coordinate;
Annotation *annotation = [[Annotation alloc] init];
annotation.image = [UIImage imageNamed:#"Annotation"];
if (contact.thumbnail.size.width > 0){
annotation.image = contact.thumbnail;
}
else{
annotation.image = [UIImage imageNamed:#"Annotation"];
}
annotation.coordinate = coordinate;
[self.mapView addAnnotation:annotation];
}
else if (error){
NSLog(#"ERROR");
}
}
];
}];
}
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
CustomAnnotationView *returnedAnnotationView = nil;
if ([annotation isKindOfClass:[Annotation class]])
{
returnedAnnotationView = (CustomAnnotationView *)[Annotation createViewAnnotationForMapView:self.mapView annotation:annotation];
}
return returnedAnnotationView;
}
However, when I scroll across self.mapView, the incorrect contact images are showing for the wrong annotations. I'm not sure how to fix this. Any help would be much appreciated. Thanks
I added a property to my custom annotation view and simply changed the image everytime I dequeued or created a new annotation.
#property (nonatomic, strong) UIImageView *annotationImage;

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
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;
}
}

Gettin Bad Access while adding Annotations

I´m trying to to add many Annotations (depends on how many objects a have in my Array) to my Mapview like this:
-(void)viewWillAppear:(BOOL)animated
{
[mapView removeAnnotations:mapView.annotations];
for (Daten *info in datenArray) {
CLLocationCoordinate2D location;
location.latitude = (double)[info.lati doubleValue];
location.longitude = (double)[info.longi doubleValue];
MapPin *newAnnotation =[[[MapPin alloc] initWithTitle:info.rating andCoordinate:location] autorelease];
[mapView addAnnotation:newAnnotation];
}
[self zoomToFitMapAnnotations:self.mapView];
[self.mapView selectAnnotation:self.mapView.annotations.lastObject animated:YES];
}
The first time I switch to that View it works perfectly...But if i come a second time to this View, i get this Bad Access with Error:
*** -[CFString length]: message sent to deallocated instance 0x17e140c0
Edit:
Thats my MapPin Class:
#interface MapPin : NSObject <MKAnnotation> {
NSString *title;
NSString *subtitle;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, readonly, copy) NSString *subtitle;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d;
EDIT2:
Edit3:
Here´s the implementation:
#import "MapPin.h"
#implementation MapPin
#synthesize title, coordinate, subtitle;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
[super init];
subtitle = ttl;
title = #"Rating:";
coordinate = c2d;
return self;
}
- (void)dealloc {
[title release];
[subtitle release];
[super dealloc];
}
#end
You should send retain or copy message for object in init.
if (self = [super init]) {
subtitle = [ttl copy];
title = [#"Rating:" retain]
...
}
return self;
#"Rating:" is equal method which create autoreleased object.
Or you can use self.title = #"Rating:";.

Resources