i'm just playing around with Apple's CurrentAddress sample code and I was trying to use the trueHeading property to determine the direction the user is facing. While that proved simple enough, I wanted to display a transparent PNG on top of the current location dot and I wanted to rotate it in order to simulate a compass.
Here's the very basic code I've currently got:
#implementation MapViewController
#synthesize mapView, reverseGeocoder, getAddressButton;
- (void)viewDidLoad
{
[super viewDidLoad];
mapView.showsUserLocation = YES;
}
- (IBAction)reverseGeocodeCurrentLocation
{
self.reverseGeocoder =
[[[MKReverseGeocoder alloc] initWithCoordinate:mapView.userLocation.location.coordinate] autorelease];
reverseGeocoder.delegate = self;
[reverseGeocoder start];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
{
NSString *errorMessage = [error localizedDescription];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Cannot obtain address."
message:errorMessage
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{
PlacemarkViewController *placemarkViewController =
[[PlacemarkViewController alloc] initWithNibName:#"PlacemarkViewController" bundle:nil];
placemarkViewController.placemark = placemark;
[self presentModalViewController:placemarkViewController animated:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// we have received our current location, so enable the "Get Current Address" button
[getAddressButton setEnabled:YES];
NSString *north = [NSString stringWithFormat:#"%f", self.mapView.userLocation.heading.trueHeading];
NSLog(#"here: %#", north);
}
#end
How can I overlay the PNG to the exact position of the blue dot and keep it there (following the dot if the user moves, that is)?
The point is that you need to implement mapView:viewForAnnotation: delegate method and look inside it for annotation objects which are not yours. Take a look at the code snipped:
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation {
NSString static *defaultID = #"defaultID";
NSString static *userLocationID = #"userLocationID";
if ([annotation isKindOfClass:[MyAnnotation class]]) {
// your code here
} else {
MKAnnotationView *annotationView = [map dequeueReusableAnnotationViewWithIdentifier:userLocationID];
if (!annotationView) {
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:userLocationID] autorelease];
annotationView.image = [UIImage imageNamed:#"UserLocationIcon.png"];
}
return annotationView;
}
}
Related
in my first iOS app I've got a map displaying annotations for several locations. It works perfectly in the simulator and looks like this:
But on all devices the annotations are not located right. They are all placed at latitude 0 and longitude 0.
Do you have any ideas?
Here is my Source Code:
MapViewController.m
//
// MapViewController.m
//
#import "MapViewController.h"
#import "AppDelegate.h"
#import "Location.h"
#import <MapKit/MapKit.h>
#import "Reachability.h"
#import "MyAnnotation.h"
#interface MapViewController ()
#end
#implementation MapViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.mapView.delegate = self;
//User location
self.locationManager = [[CLLocationManager alloc]init];
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
[self loadOfflineMap];
[self addAnnotations:[(AppDelegate *)[[UIApplication sharedApplication] delegate] locations]];
//Set initial region
MKCoordinateRegion region = [self.mapView regionThatFits:MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(53.868223, 10.689060), 3000, 3000)];
//Set initial locatoin if one is set
if(self.initialLocationName != nil){
for (id<MKAnnotation> annotation in [self.mapView annotations]) {
if([[annotation title] isEqualToString:self.initialLocationName]){
[self.mapView selectAnnotation:annotation animated:YES];
region = [self.mapView regionThatFits:MKCoordinateRegionMakeWithDistance([annotation coordinate], 500, 500)];
}
}
}
[self.mapView setRegion:region animated:YES];
//Layout stuff
self.locationName.font = [UIFont fontWithName:#"CenturyGothic" size:self.locationName.font.pointSize];
self.locationAddress.font = [UIFont fontWithName:#"CenturyGothic" size:self.locationAddress.font.pointSize];
}
-(void)addAnnotations:(NSMutableArray *)locations{
self.locationNameToAnnotation = [[NSMutableDictionary alloc] init];
for(Location *location in locations){
MyAnnotation *annotation = [[MyAnnotation alloc] initWithTitle:location.name AndCoordinate:CLLocationCoordinate2DMake([location.latitude doubleValue], [location.longitude doubleValue])];
[self.locationNameToAnnotation setObject:annotation forKey:location.name];
[self.mapView addAnnotation:annotation];
}
}
-(void)mapView:(MKMapView * )mapView didSelectAnnotationView:(MKAnnotationView * )view{
for(NSString *locationName in self.locationNameToAnnotation){
if([locationName isEqualToString:view.annotation.title]){
Location *location = [Location getLocationFromLocations:[(AppDelegate *)[[UIApplication sharedApplication] delegate] locations] byName:locationName];
self.locationName.text = location.name;
self.locationAddress.text = location.address;
}
}
self.locationInfoView.hidden = NO;
[self.mapView setCenterCoordinate:view.annotation.coordinate animated:YES];
}
-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view{
self.locationInfoView.hidden = YES;
}
-(void)loadOfflineMap{
self.mapView.delegate = self;
NSString *baseURL = [[[NSBundle mainBundle] bundleURL] absoluteString];
NSString *template = [baseURL stringByAppendingString:#"{x}-{y}.jpg"];
self.overlay = [[MKTileOverlay alloc] initWithURLTemplate:template];
self.overlay.canReplaceMapContent = YES;
self.overlay.minimumZ = 12;
self.overlay.maximumZ = 19;
[self.mapView addOverlay:self.overlay level:MKOverlayLevelAboveLabels];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
}
- (IBAction)mapTypeChanged:(UISegmentedControl *)sender {
if(sender.selectedSegmentIndex == 1){
if([self checkIntetnetConnection] == YES){
[self.mapView removeOverlay:self.overlay];
}else{
sender.selectedSegmentIndex = 0;
}
}else if(sender.selectedSegmentIndex == 0){
[self.mapView addOverlay:self.overlay level:MKOverlayLevelAboveLabels];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)checkIntetnetConnection{
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
//NSLog(#"There IS NO internet connection");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Internet" message:#"Sorry, please turn on your internet to access the online map" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
return NO;
} else {
//NSLog(#"There IS internet connection");
return YES;
}
}
#end
MyAnnotation.m
//
// MyAnnotation.m
//
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize coordinate=_coordinate;
#synthesize title=_title;
-(id) initWithTitle:(NSString *) title AndCoordinate:(CLLocationCoordinate2D)coordinate
{
self = [super init];
_title = title;
_coordinate = coordinate;
return self;
}
#end
Edit 1
Locations Array Parsing from JSON, which works fine:
-(void)createLocations:(NSDictionary *)jsonLocations{
self.locations = [[NSMutableArray alloc] init];
for(NSDictionary *jsonLocation in jsonLocations){
Location *location = [[Location alloc] init];
[location setName:jsonLocation[#"name"]];
[location setId:jsonLocation[#"id"]];
[location setLatitude:[self getNumberFromString:jsonLocation[#"latitude"]]];
[location setLongitude:[self getNumberFromString:jsonLocation[#"longitude"]]];
[location setZoomlevel:jsonLocation[#"zoomlevel"]];
[location setAddress:jsonLocation[#"address"]];
[self.locations addObject:location];
}
}
I'd really appreciate all ideas. Probably it's an easy question but since I'm new to iOS Development I'm quite frustrated right now.
Cheers Thomas!
I tired to get indexpath of my custom annotation ,
I use this code for get my indexpath
NSUInteger index =[mapView.annotations indexOfObject:view.annotation];
its not really working because in my map, i got right lat and lang but not get the true data of pinview
pusingpalagw is my subclass
here is my code:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
// [(UIImageView *)view.leftCalloutAccessoryView setImageWithURL:[NSURL URLWithString:self.content.MERCHANT_IMAGE] usingActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
//if ([view.annotation isKindOfClass:[pusingpalagw class]]) {
// pusingpalagw *annot = view.annotation;
//NSInteger index = [self.arrayOfAnnotations indexOfObject:annot];
NSUInteger index =[mapView.annotations indexOfObject:view.annotation];
if (!self.content) {
pusingpalagw *calloutView = [[pusingpalagw alloc] initWithFrame:CGRectMake(0.0, 0.0, 242.0, 57.0)];
self.content12 = [self.listContent objectAtIndex:index];
calloutView.titleLabel.text = self.content12.MERCHANT_NAME;
calloutView.subtitleLabel.text = self.content12.MERCHANT_NAME;
//UIView *rating2 = (UIView*)[cell2 viewWithTag:110];
_starRating = [[EDStarRating alloc]initWithFrame:CGRectMake(calloutView.viewRating.frame.origin.x-15, calloutView.viewRating.frame.origin.y,80,20)];
_starRating.backgroundColor = [UIColor clearColor];
self.starRating.starImage = [UIImage imageNamed:#"kuningstarkosong"];
self.starRating.starHighlightedImage = [UIImage imageNamed:#"kuningstarfull"] ;
_starRating.maxRating = 5.0;
_starRating.delegate = self;
_starRating.horizontalMargin = 15.0;
_starRating.editable=NO;
_starRating.rating= [self.content12.MERCHANT_RATTING floatValue];
_starRating.displayMode=EDStarRatingDisplayHalf;
[_starRating setNeedsDisplay];
[calloutView.viewRating addSubview:_starRating];
NSLog(#"keluarbintang%#",_starRating);
NSURL *url = [NSURL URLWithString:self.content12.MERCHANT_IMAGE];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *abs = [UIImage imageWithData:imageData];
[calloutView.imageMap setImage:abs];
//[calloutView.buttonDetail setTitle: #"Post" forState: UIControlStateNormal];
UIButton *buttonAja = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, calloutView.frame.size.width, calloutView.frame.size.height)];
[buttonAja setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//[buttonAja setTitle: #"Post" forState: UIControlStateNormal];
buttonAja.titleLabel.font = [UIFont systemFontOfSize:13.0];
[buttonAja addTarget:self action:#selector(goDetail:) forControlEvents:UIControlEventTouchUpInside];
[calloutView addSubview:buttonAja];
calloutView.center = CGPointMake(CGRectGetWidth(view.bounds) / 2.0, 0.0);
[view addSubview:calloutView];
}
//To get permission
if([CLLocationManager locationServicesEnabled]){
NSLog(#"Location Services Enabled");
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusDenied){
alert = [[UIAlertView alloc] initWithTitle:#"App Permission Denied"
message:#"To re-enable, please go to Settings and turn on Location Service for this app."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
//To set user Location
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.showsUserLocation=YES;
self.mapView.delegate = self;
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
}
...
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion mapRegion;
mapRegion.center = mapView.userLocation.coordinate;
mapRegion.span.latitudeDelta = 0.2;
mapRegion.span.longitudeDelta = 0.2;
[mapView setRegion:mapRegion animated: YES];
}
Permission for IOS 8 Or Later :-
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
if ([CLLocationManager locationServicesEnabled] )
{
if (self.locationManager == nil )
{
self.locationManager.delegate = (id)self;
self.locationManager = [[CLLocationManager alloc] init];
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER)
{
// Use one or the other, not both. Depending on what you put in info.plist
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
#endif
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kDistanceFilter; //kCLDistanceFilterNone// kDistanceFilter;
}
[self.locationManager startUpdatingLocation];
self.mapViewForPlace.showsUserLocation = YES;
[self.locationManager setDelegate:self];
NSLog(#"Location Title Is: %#", self.mapViewForPlace.userLocation.title);
}
Add info.plist NSLocationWhenInUseUsageDescription type of string.
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER) {
// Use one or the other, not both. Depending on what you put in info.plist
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
#endif
self.mapViewForPlace.showsUserLocation = YES;
self.currentLocation = [locations lastObject];
// here we get the current location
NSLog(#"Current Locations : %#",self.currentLocation);
// CLLocation* location = (CLLocation*)locations.lastObject;
// Use Apple's Geocoder to figure the name of the place
CLGeocoder* geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:self.currentLocation completionHandler: ^(NSArray* placemarks, NSError* error) {
if (error != nil) {
NSLog(#"Error in geo coder: %#", error);
}
else {
if (placemarks.count == 0) {
NSLog(#"The address couldn't be found");
}
else {
// Get nearby address
CLPlacemark* placemark = placemarks[0];
// Get the string address and store it
NSString* locatedAt = [[placemark.addressDictionary valueForKey:#"FormattedAddressLines"] componentsJoinedByString:#", "];
//location.name = locatedAt;
currentLocationNameIs=locatedAt;
NSLog(#"The address is: %#", locatedAt);
}
}
}];
}
- (void) locationManager:(CLLocationManager *) manager didUpdateToLocation:(CLLocation *) newLocation fromLocation:(CLLocation *) oldLocation
{
self.currentLocation = newLocation;
self.mapViewForPlace.showsUserLocation = YES;
NSLog(#"New location Cordinate : %f %f",self.mapViewForPlace.userLocation.coordinate.latitude,self.mapViewForPlace.userLocation.coordinate.longitude);
[self.locationManager stopUpdatingLocation];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
//pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"facebook30.png"];
pinView.calloutOffset = CGPointMake(0, 32);
// Add a detail disclosure button to the callout.
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.rightCalloutAccessoryView = rightButton;
// Add an image to the left callout.
UIImageView *iconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"facebook30.png"]];
pinView.leftCalloutAccessoryView = iconView;
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
my problem is rather simple but I can not seem to figure it out.
I am trying to add a refresh button to my mapview that will go back to the server and retrieve new locations if there have been any updates. My code below can already make the first call to the server with viewdidload method and can plot all the locations on the server to the map. What I need now is for a button that will make this same call whenever pressed, I am using one class for all my code so please your simplest solution that will easily merge with the code will be very much appreciated.
I am also very new to ios programming so any advice on how to tidy up my code will be also appreciated.
This is my view controller that contains all my code.
//ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
[self.mapView setShowsUserLocation:YES];
} else {
[locationManager requestWhenInUseAuthorization];
}
NSURL *jsonFileUrl = [NSURL URLWithString:#"http://sample.name/service.php"];
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:jsonFileUrl];
[NSURLConnection connectionWithRequest:urlRequest delegate:self];
}
#pragma mark NSURLConnectionDataProtocol Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
_downloadedData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_downloadedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSMutableArray *_locations = [[NSMutableArray alloc] init];
NSError *error;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:_downloadedData options:NSJSONReadingAllowFragments error:&error];
CLLocationCoordinate2D coordinate;
for (int i = 0; i < jsonArray.count; i++)
{
NSDictionary *jsonElement = jsonArray[i];
MKPointAnnotation* marker = [[MKPointAnnotation alloc] init];
marker.title = jsonElement[#"Name"];
marker.subtitle = jsonElement[#"Address"];
coordinate.latitude = [jsonElement [#"Latitude"] doubleValue];
coordinate.longitude = [jsonElement [#"Longitude"] doubleValue];
marker.coordinate = coordinate;
[_locations addObject:marker];
}
[self.mapView addAnnotations:_locations];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString *identifier;
{
if (annotation == mapView.userLocation) return nil;
MKAnnotationView *annotationView;
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"blue_pin.png"];
} else {
annotationView.annotation = annotation;
}
return annotationView;
}
return nil;
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self.mapView setShowsUserLocation:YES];
}
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
CLLocationCoordinate2D myLocation = [userLocation coordinate];
MKCoordinateRegion zoomRegion = MKCoordinateRegionMakeWithDistance(myLocation, 10000, 10000);
[self.mapView setRegion:zoomRegion animated:YES];
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)InterfaceOrientation
{
return (InterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)Refresh:(id)sender {
}
#end
You can find my solution with comment.
Remove your old data when you refresh or when you got the response.
- (IBAction)action_goToManageDevice:(id)sender
{
[self reloadData];
}
- (void)reloadData
{
// Remove old annotation
[self.mapView removeAnnotations:self.mapView.annotations];
// reload your data
NSURL *jsonFileUrl = [NSURL URLWithString:#"http://sample.name/service.php"];
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:jsonFileUrl];
[NSURLConnection connectionWithRequest:urlRequest delegate:self];
}
I have a "problem" with the following code. The error message is: Application tried to push a nil view controller on target UINavigationController:0x10b82bbf0 when clicking on annotation #4's callout.
How can I make it open an alertview without getting this error?
//Callout button action
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control{
if ([view.annotation isKindOfClass:[Annotation class]])
{
Annotation *myAnn = (Annotation *)view.annotation;
id vcToPush = nil;
if ([[myAnn title] isEqualToString:#"1. Annotation one"]){
vcToPush = [[FirstViewController alloc]init];
}
if ([[myAnn title] isEqualToString:#"2. Annotation two"]){
vcToPush = [[SecondViewController alloc]init];
}
if ([[myAnn title] isEqualToString:#"3. Annotation three"]){
vcToPush = [[ThirdViewController alloc]init];
}
if ([[myAnn title] isEqualToString:#"4. Annotation four"]){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Fourth annotation" message:#"Message" delegate:nil cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
[self.navigationController pushViewController:vcToPush animated:YES];
}
}
//Custom callout
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)myAnn {
//Current location blue dot
if ([myAnn isKindOfClass:[MKUserLocation class]])
{
((MKUserLocation *)myAnn).title = #"My position";
return nil;
}//
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"pinView"];
if (!pinView) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:myAnn reuseIdentifier:#"pinView"];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
else
{
pinView.annotation = myAnn;
}
return pinView;
}
Thank you!
In the if block
if ([[myAnn title] isEqualToString:#"4. Annotation four"]){
vcToPush is not initialize. Therefore is has the value it had before the method got called (nil in this case).
I assume you only want to show an alert in case of #4. In this case, add a return in the if block:
if ([[myAnn title] isEqualToString:#"4. Annotation four"]){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Fourth annotation" message:#"Message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
return;
}
I'm trying to call plotParkingLots from my AppDelegate as I want it to be called first when the app starts (and then every x seconds which I will implement later).
plotParkingLots works fine if I call it through my MapViewController's viewDidLoad, but when I call it from AppDelegate, it doesn't work.
I know that it is called but when I switch to my map view, no annotation is shown!
MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#define METERS_PER_MILE 1609.344
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
- (void)plotParkingLots;
#end
MapViewController.m
- (void)plotParkingLots {
NSString *url = [NSString stringWithFormat:#"http:/localhost/testes/parking.json"];
NSData *jsonData = [NSData dataWithContentsOfURL: [NSURL URLWithString:url]];
if (jsonData == nil) {
UIAlertView *alertBox = [[UIAlertView alloc] initWithTitle: #"Erro de conexão" message: #"Não foi possível retornar os dados dos estacionamentos" delegate: self cancelButtonTitle: #"Ok" otherButtonTitles: nil];
[alertBox show];
}
else {
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
NSArray *parkings = [json objectForKey:#"parkings"];
for (NSDictionary * p in parkings) {
Parking *annotation = [[Parking alloc] initWithDictionary:p];
[_mapView addAnnotation:annotation];
}
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"Parking";
if ([annotation isKindOfClass:[Parking class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.image=[UIImage imageNamed:#"car.png"];
return annotationView;
}
return nil;
}
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[[MapViewController alloc] plotParkingLots];
return YES;
}
You're not talking to the MapViewController that is displayed to the user. In your AppDelegate you momentarily allocation a MapViewController, plot the parking lots, then abandon that MapViewController and never use it again.
You'll need to keep a handle to that controller so that when the user presses something to make that viewcontroller get displayed it is the same one that has just plotted the parking lots.