I am trying to add pins to a couple of locations I created in one of my classes, which is called "Places".
The key to these locations is defined as "places_coordinates".
I tried to place those pins as follows:
View Controller.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import <Parse/Parse.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate, MKMapViewDelegate>
#property (nonatomic, retain) CLLocationManager *locationManager;
#property(nonatomic, strong) MKPinAnnotationView *geoPointAnnotation;
#property(nonatomic, strong)MKPointAnnotation *annotation;
#property(nonatomic, strong)CLLocation *location;
#property (nonatomic, strong) PFObject *detailItem;
#property (weak, nonatomic) IBOutlet MKMapView *appleMap;
#end
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
if (nil == self.locationManager){
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
//Configure Accuracy depending on your needs, default is kCLLocationAccuracyBest
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
self.locationManager.distanceFilter = 500; // meters
[self.locationManager startUpdatingLocation];
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
self.appleMap.delegate = self;
// Map will show current location
self.appleMap.showsUserLocation = YES;
// Maps' opening spot
self.location = [self.locationManager location];
CLLocationCoordinate2D coordinateActual = [self.location coordinate];
// Map's zoom
MKCoordinateSpan zoom = MKCoordinateSpanMake(0.010, 0.010);
// Create a region
MKCoordinateRegion region = MKCoordinateRegionMake(coordinateActual, zoom);
// Method which sets exibition method
[self.appleMap setRegion:region animated:YES];
//Map's type
self.appleMap.mapType = MKMapTypeStandard;
}
#pragma mark - Location Manager Callbacks
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
[PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geoPoint, NSError *error) {
if (!error) {
// Create Object
PFObject *offersLocation = [PFObject objectWithClassName:#"Places"];
//Create a point for markers
PFGeoPoint *offersPoint = offersLocation[#"places_coordinate"];
// Check current Location
NSLog(#"%#", offersPoint);
// Create a query for Places of interest near current location
PFQuery *query = [PFQuery queryWithClassName:#"Places"];
[query whereKey:#"places_coordinate" nearGeoPoint:geoPoint withinKilometers:5.0];
NSLog(#"Query: %#",query);
// Limit the query
query.limit = 10;
// Store objects in the array
NSArray *offersArray = [query findObjects];
NSLog(#"Array: %#",offersArray);
if (!error) {
for (query in offersArray) {
self.annotation = [[MKPointAnnotation alloc]
init];
CLLocationCoordinate2D coord = {offersPoint.latitude, offersPoint.longitude};
self.annotation.coordinate = coord ;
[self.appleMap addAnnotation:self.annotation];
NSLog(#"Annotation: %#",self.annotation);
}
}
}
}];
}
#pragma mark - MKMapViewDelegate
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
static NSString *MapViewAnnotationIdentifier = #"places_coordinate";
MKPinAnnotationView *pinOffers = [[MKPinAnnotationView alloc] initWithAnnotation:self.annotation reuseIdentifier:MapViewAnnotationIdentifier];
pinOffers.pinColor = MKPinAnnotationColorRed;
pinOffers.canShowCallout = YES;
pinOffers.animatesDrop = YES;
return pinOffers;
}
My log is showing all offers inside the offersArray, but I am not finding a way of putting markers in it.
I also tried a couple of other topics, but did not really get it:
how to add multiple pin at the same lat/long
Adding mapview annotations within parse query returns null randomly
Best Regards,
What was happening was that my for loop was not built correctly.
It should be like this:
...
if (!error) {
for (PFObject *offerObject in offersArray) {
PFGeoPoint *offerPoint = [offerObject objectForKey:#"coordenadas"];
MKPointAnnotation *geoPointAnnotation = [[MKPointAnnotation alloc]
init];
geoPointAnnotation.coordinate = CLLocationCoordinate2DMake(offerPoint.latitude, offerPoint.longitude);
[self.appleMap addAnnotation:geoPointAnnotation];
NSLog(#"Annotation: %#",geoPointAnnotation);
}
}
...
Related
I am developing an app using Google Map iOS SDK (Objective C).
Done so far:
Loaded markers from the server in map view
Generate random clusters only.
When I run the project it looks like this.
Screen shot of map view
It shows both markers and clusters both in the map view at zoom level 10. But I wanted to show clusters first then when I zoomed in it should show the real markers. Not the randomly generated markers that I created because I don't know a way to show the clusters in the map.
Here is the full code with fake URL link:
#import "ViewController.h"
//#import "CSMarker.h"
#import <GoogleMaps/GoogleMaps.h>
#import <Google-Maps-iOS-Utils/GMUMarkerClustering.h>
//importing POI Item object - points of interest
#interface POIItem : NSObject<GMUClusterItem>
#property(nonatomic, readonly) CLLocationCoordinate2D position;
#property(nonatomic, readonly) NSString *name;
- (instancetype)initWithPosition:(CLLocationCoordinate2D)position name:(NSString *)name;
#end
#implementation POIItem
- (instancetype)initWithPosition:(CLLocationCoordinate2D)position name:(NSString *)name {
if ((self = [super init])) {
_position = position;
_name = [name copy];
}
return self;
}
#end
//implementation start - map view controller
static const NSUInteger kClusterItemCount = 60;
static const double kCameraLatitude = 25.277683999999997;
static const double kCameraLongitude = 55.309802999999995;
#interface ViewController ()<GMUClusterManagerDelegate, GMSMapViewDelegate>
{
NSMutableArray *waypoints_;
NSMutableArray *waypointStrings_;
GMSMapView *_mapView;
GMUClusterManager *_clusterManager;
}
#property(strong, nonatomic) NSURLSession *markerSession;
#property(strong, nonatomic) GMSMapView *mapView;
#property(copy, nonatomic) NSSet *markers;
#property(nonatomic, strong) NSMutableArray *markersArray;
#end
#implementation ViewController
#synthesize gs;
- (void)viewDidLoad {
[super viewDidLoad];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:kCameraLatitude
longitude:kCameraLongitude
zoom:10];
self.mapView =
[GMSMapView mapWithFrame:self.view.bounds camera:camera];
[self.view addSubview:self.mapView];
self.mapView.settings.compassButton = YES;
self.mapView.settings.myLocationButton = YES;
//setup the cluster manager
NSURLSessionConfiguration *config =
[NSURLSessionConfiguration defaultSessionConfiguration];
config.URLCache = [[NSURLCache alloc] initWithMemoryCapacity:2 * 1024 * 1024
diskCapacity:10 * 1024 * 1024
diskPath:#"MarkerData"];
self.markerSession = [NSURLSession sessionWithConfiguration:config];
[self downloadMarkerData];
//cluster load setup
id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];
id<GMUClusterRenderer> renderer =
[[GMUDefaultClusterRenderer alloc] initWithMapView:self.mapView
clusterIconGenerator:iconGenerator];
_clusterManager =
[[GMUClusterManager alloc] initWithMap:self.mapView algorithm:algorithm renderer:renderer];
// Generate and add random items to the cluster manager.
[self generateClusterItems];
// Call cluster() after items have been added to perform the clustering and rendering on map.
[_clusterManager cluster];
// Register self to listen to both GMUClusterManagerDelegate and GMSMapViewDelegate events.
[_clusterManager setDelegate:self mapDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSMutableArray *)markersArray
{
if (!_markersArray) {
_markersArray = [NSMutableArray array];
}
return _markersArray;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//downloading marker data
- (void)downloadMarkerData {
NSURL *lakesURL =
[NSURL URLWithString:#"http://myscrap.com/xxx.php/webservice/xxx/xxxx"];
NSURLSessionDataTask *task = [self.markerSession dataTaskWithURL:lakesURL
completionHandler:^(NSData *data, NSURLResponse *response, NSError *e)
{
NSArray *json = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
NSLog(#"json: %#",json);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self createMarkerObjectsWithJson:json];
}];
}];
[task resume];
}
-(void)drawMarkers
{
for(GMSMarker *marker in self.markers) {
if(marker.map == nil) {
marker.map = self.mapView;
}
}
}
-(void)createMarkerObjectsWithJson:(NSArray *)json
{
NSMutableSet *mutableSet = [[NSMutableSet alloc] initWithSet:self.markers];
for (NSDictionary *markerData in json) {
GMSMarker *newMarker = [[GMSMarker alloc] init];
// newMarker.appearAnimation = [markerData[#"id"] integerValue];
newMarker.position = CLLocationCoordinate2DMake([markerData[#"latitud"] doubleValue],
[markerData[#"longitude"] doubleValue]);
newMarker.title = markerData[#"name"];
newMarker.snippet = markerData[#"adress"];
// [mutableSet addObject:newMarker];
newMarker.map=self.mapView;
}
self.markers =[mutableSet copy];
[self drawMarkers];
}
#pragma mark GMUClusterManagerDelegate
- (void)clusterManager:(GMUClusterManager *)clusterManager didTapCluster:(id<GMUCluster>)cluster {
GMSCameraPosition *newCamera =
[GMSCameraPosition cameraWithTarget:cluster.position zoom:_mapView.camera.zoom + 1];
GMSCameraUpdate *update = [GMSCameraUpdate setCamera:newCamera];
[_mapView moveCamera:update];
}
#pragma mark GMSMapViewDelegate
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
POIItem *poiItem = marker.userData;
if (poiItem != nil) {
NSLog(#"Did tap marker for cluster item %#", poiItem.name);
} else {
NSLog(#"Did tap a normal marker");
}
return NO;
}
#pragma mark Private
// Randomly generates cluster items within some extent of the camera and adds them to the
// cluster manager.
- (void)generateClusterItems {
const double extent = 0.2;
for (int index = 1; index <= kClusterItemCount; ++index) {
double lat = kCameraLatitude + extent * [self randomScale];
double lng = kCameraLongitude + extent * [self randomScale];
NSString *name = [NSString stringWithFormat:#"Item %d", index];
id<GMUClusterItem> item =
[[POIItem alloc] initWithPosition:CLLocationCoordinate2DMake(lat, lng) name:name];
[_clusterManager addItem:item];
}
}
// Returns a random value between -1.0 and 1.0.
- (double)randomScale {
return (double)arc4random() / UINT32_MAX * 2.0 - 1.0;
}
try changing in view did load
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:kCameraLatitude longitude:kCameraLongitude zoom:4];
the zoom to a 5 or 4. It then should show the clusters and not the markers. When you zoom in, it will show the "real" markers.
I am making an app with a map that shows the location that you type in a text field, also if you move around the map it displays on the text field the address of the location that you are looking at.
When I move around the map it display the address in the text field and shows only the street, but I was wondering if it is possible to show the address as is used in Colombia, for example: Carrera 1 # 18A - 12.If you type the address like the example in the text field it works and it founds it in the map, but does not display the address in the text field as I want.
Here is the code I am using.
If somebody can help me i would really appreciate it.
Thanks
.h file
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface ViewControllerMapaDestinoCasa : UIViewController < UITextFieldDelegate, MKMapViewDelegate>
#property (strong, nonatomic) CLLocation *ubicacionSeleccionada;
#property (strong, nonatomic) NSMutableDictionary *lugarDiccionario;
#property (strong, nonatomic) IBOutlet MKMapView *mapa;
#property (strong, nonatomic) IBOutlet UITextField *textFieldDireccion;
- (IBAction)botonUbicacionActual:(id)sender;
#end
.m file
#import "ViewControllerMapaDestinoCasa.h"
#interface ViewControllerMapaDestinoCasa ()
#end
#implementation ViewControllerMapaDestinoCasa
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.textFieldDireccion.delegate = self;
self.mapa.delegate = self;
self.lugarDiccionario = [[NSMutableDictionary alloc] init];
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 4.609886;
zoomLocation.longitude= -74.08205;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 1609.344,1609.344);
[self.mapa setRegion:viewRegion animated:YES];
}
- (IBAction)botonUbicacionActual:(id)sender {
[self updatePlaceDictionary];
[self updateMaps];
}
- (void)updatePlaceDictionary {
[self.lugarDiccionario setValue:self.textFieldDireccion.text forKey:#"Street"];
[self.lugarDiccionario setValue:#"Bogotá" forKey:#"City"];
[self.lugarDiccionario setObject:#"Colombia" forKey:#"Country"];
}
- (void)updateMaps {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressDictionary:self.lugarDiccionario completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count]) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocationCoordinate2D coordinate = location.coordinate;
[self.mapa setCenterCoordinate:coordinate animated:YES];
} else {
NSLog(#"error");
}
}];
}
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
self.ubicacionSeleccionada =
[[CLLocation alloc] initWithLatitude:mapView.centerCoordinate.latitude
longitude:mapView.centerCoordinate.longitude];
[self performSelector:#selector(delayedReverseGeocodeLocation)
withObject:nil
afterDelay:0.3];
}
- (void)delayedReverseGeocodeLocation {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self reverseGeocodeLocation];
}
- (void)reverseGeocodeLocation {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:self.ubicacionSeleccionada completionHandler:^(NSArray *placemarks, NSError *error) {
if(placemarks.count){
NSDictionary *dictionary = [[placemarks objectAtIndex:0] addressDictionary];
[self.textFieldDireccion setText:[dictionary valueForKey:#"Street"]];
}
}];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
#end
Here is the code I use to get the full address, if I understood your question correctly.
[geocoder reverseGeocodeLocation:touchLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (!error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
// Update annotation with address
self.person.address.state = placemark.administrativeArea;
self.person.address.city = placemark.locality;
NSString *placemarkAddress;
//Accounts for the possibility of the number or street being null
if (placemark.subThoroughfare && placemark.thoroughfare){
placemarkAddress = [NSString stringWithFormat:#"%# %#",placemark.subThoroughfare, placemark.thoroughfare];
}
else if (placemark.thoroughfare){
placemarkAddress = placemark.thoroughfare;
}
self.person.address.street1 = placemarkAddress;
self.person.address.zip = placemark.postalCode;
}
else {
//Error
}
}];
I am trying to provide directions to certain areas I have marked with map pins on my map view. On those pins I have displayed the name of the location and where it is located. I would like for them to be able to click the "i" that is usually on some Apple "pop ups" and it direct them to the Maps app and give them directions based on the coordinates I programmed in to place the map pin where it is. I will post two pictures first of what I have and what I would like to accomplish.
What I have right now
What I want to add to my pin (just the "i")
Now I will post my code of how I accomplished my first screenshot.
ViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController
{
MKMapView *mapView;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
-(IBAction)SetMap:(id)sender;
-(IBAction)GetLocation:(id)sender;
-(IBAction)Directions:(id)sender;
#end
ViewController.m:
#import "ViewController.h"
#import "MapPin.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
//Moss Preserve coordinates
MKCoordinateRegion MossPreserveRegion = { {0.0, 0.0}, {0.0, 0.0}};
MossPreserveRegion.center.latitude = 33.3816566;
MossPreserveRegion.center.longitude = -86.8415451;
MossPreserveRegion.span.longitudeDelta = 55.0;
MossPreserveRegion.span.latitudeDelta = 55.0;
[mapView setRegion:MossPreserveRegion animated:YES];
//Moss Preserve annotation and map pin
MapPin *MossPreserveAnnotation = [[MapPin alloc] init];
MossPreserveAnnotation.title = #"Moss Rock Preserve Boulder Fields";
MossPreserveAnnotation.subtitle = #"Hoover, AL";
MossPreserveAnnotation.coordinate = MossPreserveRegion.center;
[mapView addAnnotation:MossPreserveAnnotation];
//Horse Pens 40 coordinates
MKCoordinateRegion HorsePenRegion = { {0.0, 0.0}, {0.0, 0.0}};
HorsePenRegion.center.latitude = 33.9207535;
HorsePenRegion.center.longitude = -86.3089447;
HorsePenRegion.span.longitudeDelta = 55.0;
HorsePenRegion.span.latitudeDelta = 55.0;
[mapView setRegion:HorsePenRegion animated:YES];
//Horse Pens 40 annotation and map pin
MapPin *HorsePenAnnotation = [[MapPin alloc] init];
HorsePenAnnotation.title = #"Horse Pens 40";
HorsePenAnnotation.subtitle = #"Steele, AL ";
HorsePenAnnotation.coordinate = HorsePenRegion.center;
[mapView addAnnotation:HorsePenAnnotation];
// Create an MKMapItem to pass to the Maps app
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:MossPreserveAnnotation.coordinate
addressDictionary:nil];
MKMapItem *mossPreserveMapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mossPreserveMapItem setName:MossPreserveAnnotation.title];
NSDictionary *launchOptions = #{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};
// Get the "Current User Location" MKMapItem
placemark = [[MKPlacemark alloc] initWithCoordinate:HorsePenRegion.coordinate
addressDictionary:nil];
MKMapItem *horsePenMapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
horsePenmapItem.name = HorsePenRegion.title;
// Pass the current location and destination map items to the Maps app
// Set the direction mode in the launchOptions dictionary
[MKMapItem openMapsWithItems:#[mossPreserveMapItem, horsePenmapItem]
launchOptions:launchOptions];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)SetMap:(id)sender;
{
switch (((UISegmentedControl *) sender).selectedSegmentIndex)
{
case 0:
mapView.mapType = MKMapTypeStandard;
break;
case 1:
mapView.mapType = MKMapTypeSatellite;
break;
case 2:
mapView.mapType = MKMapTypeHybrid;
break;
default:
break;
}
}
-(IBAction)GetLocation:(id)sender;
{
mapView.showsUserLocation = YES;
}
-(IBAction)Directions:(id)sender;
{
NSString *urlString = #"http://maps.apple.com/maps?daddr=33.3816566,-86.8415451";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
#end
MapPin.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
MapPin.m:
#import "MapPin.h"
#implementation MapPin
#synthesize coordinate, title, subtitle;
#end
I see this all of the time in apps that I use. i just don't even really know what it is called, so I could even search for it. I am not looking for someone to hold my hand and tell me the answer, just some proper guidance and constructive criticism.
Thanks
Is this what you need?
#import "MapViewController.h"
#import "MapPin.h"
#import MapKit;
#interface MapViewController ()<MKMapViewDelegate>
#property (nonatomic, weak) IBOutlet MKMapView *mapView;
#end
#implementation MapViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_mapView.delegate = self;
//Moss Preserve coordinates
MKCoordinateRegion MossPreserveRegion = { {0.0, 0.0}, {0.0, 0.0}};
MossPreserveRegion.center.latitude = 33.3816566;
MossPreserveRegion.center.longitude = -86.8415451;
MossPreserveRegion.span.longitudeDelta = 55.0;
MossPreserveRegion.span.latitudeDelta = 55.0;
[_mapView setRegion:MossPreserveRegion animated:YES];
//Moss Preserve annotation and map pin
MapPin *MossPreserveAnnotation = [[MapPin alloc] init];
MossPreserveAnnotation.title = #"Moss Rock Preserve Boulder Fields";
MossPreserveAnnotation.subtitle = #"Hoover, AL";
MossPreserveAnnotation.coordinate = MossPreserveRegion.center;
[_mapView addAnnotation:MossPreserveAnnotation];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
// Create an MKMapItem to pass to the Maps app
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:view.annotation.coordinate
addressDictionary:nil];
MKMapItem *mossPreserveMapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mossPreserveMapItem setName:view.annotation.title];
NSDictionary *launchOptions = #{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};
// Get the "Current User Location" MKMapItem
MKMapItem *currentLocationItem = [MKMapItem mapItemForCurrentLocation];
[MKMapItem openMapsWithItems:#[mossPreserveMapItem, currentLocationItem]
launchOptions:launchOptions];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:#"MKPinAnnotationView"];
annotationView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
annotationView.rightCalloutAccessoryView = detailButton;
return annotationView;
}
You need to create 2 map items for your locations and pass as arguments to MKMapItem's openMapsWithItems:launchOptions:
// Create an MKMapItem to pass to the Maps app
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:MossPreserveAnnotation.coordinate
addressDictionary:nil];
MKMapItem *mapItem1 = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:MossPreserveAnnotation.title];
NSDictionary *launchOptions = #{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};
// Get the "Current User Location" MKMapItem
placemark = [[MKPlacemark alloc] initWithCoordinate:HorsePenAnnotation.coordinate
addressDictionary:nil];
MKMapItem *mapItem2 = [[MKMapItem alloc] initWithPlacemark:placemark];
mapItem2.name = HorsePenAnnotation.title;
// Pass the current location and destination map items to the Maps app
// Set the direction mode in the launchOptions dictionary
[MKMapItem openMapsWithItems:#[mapItem1, mapItem2]
launchOptions:launchOptions];
I'm making a application where the user sets the adres in an UITextField and gets a location on the map.
I want the cityOutlet to be invisible but be fixed at the city 'Amsterdam'.
Is there an way to do this? I couldn't find a way to fix this, or am I stupid..
#property (weak, nonatomic) IBOutlet UITextField *addressOutlet;
#property (weak, nonatomic) IBOutlet UITextField *cityOutlet;
#property (strong, nonatomic) CLLocation *selectedLocation;
#property (strong, nonatomic) NSMutableDictionary *placeDictionary;
- (void)viewDidLoad
{
[super viewDidLoad];
self.addressOutlet.delegate = self;
self.cityOutlet.delegate = self;
self.mapView.delegate = self;
self.placeDictionary = [[NSMutableDictionary alloc] init];
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 40.740848;
zoomLocation.longitude= -73.991134;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 1609.344,1609.344);
[self.mapView setRegion:viewRegion animated:YES];
}
- (void)updatePlaceDictionary {
[self.placeDictionary setValue:self.addressOutlet.text forKey:#"Street"];
[self.placeDictionary setValue:self.cityOutlet.text forKey:#"City"];
}
- (void)updateMaps {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressDictionary:self.placeDictionary completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count]) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
CLLocation *location = placemark.location;
CLLocationCoordinate2D coordinate = location.coordinate;
[self.mapView setCenterCoordinate:coordinate animated:YES];
} else {
NSLog(#"error, geen adres gevonden");
}
}];
}
- (void)delayedReverseGeocodeLocation {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self reverseGeocodeLocation];
}
- (void)reverseGeocodeLocation {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:self.selectedLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if(placemarks.count){
NSDictionary *dictionary = [[placemarks objectAtIndex:0] addressDictionary];
[self.addressOutlet setText:[dictionary valueForKey:#"Street"]];
[self.cityOutlet setText:[dictionary valueForKey:#"City"]];
}
}];
}
- (IBAction)submitTapped:(id)sender {
[self updatePlaceDictionary];
[self updateMaps];
}
in -viewDidLoad to hide the UILabel outlet and set its text try this:
self.cityOutlet.text = #"Amsterdam";
self.cityOutlet.hidden = YES;
Then comment out/remove this line in your reverse geocode location method:
//[self.cityOutlet setText:[dictionary valueForKey:#"City"]];
Alternatively, if you're not using the cityOutlet label for anything but holding a string, try just using an NSString property in your implementation file instead of the outlet.
#property (nonatomic, strong) NSString* cityName;
I have this code:
// MapViewController.h
#import <Foundation/Foundation.h>
#import "MyCLController.h"
#import <MapKit/MapKit.h>
#class ShowsContainerController;
#interface MapViewController : UIViewController <MyCLControllerDelegate,MKMapViewDelegate> {
MyCLController *locationController;
MKMapView *mapView;
}
- (void)locationUpdate:(CLLocation *)location;
- (void)locationError:(NSError *)error;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (assign) BOOL updateMap;
#property (strong) ShowsContainerController *parent;
#end
// MapViewController.m
#import "MapViewController.h"
#import "ShowsContainerController.h"
#define METERS_PER_MILE 1609.344
#implementation MapViewController
#synthesize parent, mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.updateMap = YES;
locationController = [[MyCLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
mapView.delegate = self;
}
- (void)locationUpdate:(CLLocation *)location {
if( self.updateMap ){
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);
[mapView setRegion:viewRegion animated:YES];
self.parent = (ShowsContainerController *)self.parentViewController;
[self.parent setLocation:location];
self.updateMap = NO;
}
}
- (void)locationError:(NSError *)error {
NSLog([error localizedDescription]);
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.parent.mapReady = YES;
if( self.parent.locationSet ){
[self.parent callApi];
}
}
#pragma mark MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"delegating user location");
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
NSLog(#"delegating pins");
static NSString* ShowAnnotationIdentifier = #"showAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
[mapView dequeueReusableAnnotationViewWithIdentifier:ShowAnnotationIdentifier];
if (!pinView)
{
// if an existing pin view was not available, create one
MKPinAnnotationView* customPinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:ShowAnnotationIdentifier];
customPinView.enabled = YES;
customPinView.pinColor = MKPinAnnotationColorRed;
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
#pragma mark -
#end
And here's the code adding my pins; it isn't fired until an api call is made, which is after viewDidAppear is fired:
- (void)placeAnnotations:(NSArray *)shows
{
NSEnumerator *e = [shows objectEnumerator];
id show;
NSMutableArray *annotations = [[NSMutableArray alloc] init];
while (show = [e nextObject]) {
double lat = [[[[[show objectForKey:#"venue"] objectForKey:#"location"] objectForKey:#"geo:point"] objectForKey:#"geo:lat"] doubleValue];
double lng = [[[[[show objectForKey:#"venue"] objectForKey:#"location"] objectForKey:#"geo:point"] objectForKey:#"geo:long"] doubleValue];
ShowAnnotation *annotation = [[ShowAnnotation alloc]
initWithCoordinate:CLLocationCoordinate2DMake(lat, lng)
withMap:self.mapController.mapView
withTitle:[show objectForKey:#"title"]
withSubtitle:[[show objectForKey:#"venue"] objectForKey:#"name" ]];
[annotations addObject:annotation];
}
NSLog(#"adding annotations");
[self.mapController.mapView addAnnotations:annotations];
}
The log shows "delegating user location", but never "delegating pins". It doesn't even fire viewForAnnotation more than the one initial time for the user's location.
The delegation seems to be working, otherwise I wouldn't be able to capture this selector, but why is it firing for only the user location and not firing for subsequent annotation additions?