I need to add 'xx' amout of random annotations to an MKMapView, within a certain range of the user's current location. But i can't figure out how to do it.
Can some of you help me?
Something like this might help:
for(int i=0;i<10;i++) {
CGFloat latDelta = rand()*0.125/RAND_MAX - 0.02;
CGFloat lonDelta = rand()*0.130/RAND_MAX - 0.08;
CLLocationCoordinate2D newCoord = {myLocation.coordinate.latitude+latDelta, myLocation.coordinate.longitude+lonDelta};
DisplayMap *ann = [[DisplayMap alloc] init];
ann.title = #"Some Pin";
ann.subtitle = [NSString stringWithFormat:#"Pin %i subtitle",i+1];
ann.coordinate = newCoord;
[mapView addAnnotation:ann];
[ann release];
}
where:
myLocation is a CLLocation instance.
DisplayMap is:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface DisplayMap : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property(nonatomic, assign) CLLocationCoordinate2D coordinate;
#property(nonatomic, copy) NSString *title;
#property(nonatomic, copy) NSString *subtitle;
#end
Related
Hi all i have a mysql database that consists of 7 columns and i have a script that reads it and extracts the data as JSON which i have pulled into an NSMutableArray, I want to be able to use this array to setup annotations on my Map but i'm not sure what to do here, as you can see i have defined one annotation here which shows up no problem but i'm honestly not sure how to show the NSMutableArray items? The NSMutable array will have more information than needed for the Annotations, I only need, coordinate, title and subtitle so how can i go about doing this? Here is my code so far:
hazards.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Hazards : NSObject <MKAnnotation>
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, strong) NSString * ID;
#property (nonatomic, strong) NSString * ROUTE;
#property (nonatomic, strong) NSString * ADDRESS;
#property (nonatomic, strong) NSString * LATITUDE;
#property (nonatomic, strong) NSString * LONGITUDE;
#property (nonatomic, strong) NSString * HAZARD;
#property (nonatomic, strong) NSString * RISK;
// Methods
- (id) initWithID: (NSString *) hazardsID andROUTE: (NSString *) hazardsROUTE andADDRESS: (NSString *) hazardsADDRESS andLATITUDE: (NSString *) hazardsLATITUDE andLONGITUDE: (NSString *) hazardsLONGITUDE andHAZARD: (NSString *) hazardsHAZARD andRISK: (NSString *) hazardsRISK;
#end
hazards.m
#import "Hazards.h"
#implementation Hazards
#synthesize coordinate, title, subtitle, ID, ROUTE, ADDRESS, LATITUDE, LONGITUDE, HAZARD, RISK;
- (id) initWithID: (NSString *) hazardsID andROUTE: (NSString *) hazardsROUTE andADDRESS: (NSString *) hazardsADDRESS andLATITUDE: (NSString *) hazardsLATITUDE andLONGITUDE: (NSString *) hazardsLONGITUDE andHAZARD: (NSString *) hazardsHAZARD andRISK: (NSString *) hazardsRISK {
self = [super init];
if (self)
{
ID = hazardsID;
ROUTE = hazardsROUTE;
ADDRESS = hazardsADDRESS;
LATITUDE = hazardsLATITUDE;
LONGITUDE = hazardsLONGITUDE;
HAZARD = hazardsHAZARD;
RISK = hazardsRISK;
}
return self;
}
#end
viewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "Hazards.h"
#interface ViewController : UIViewController
#property (nonatomic, strong) NSMutableArray *json;
#property (nonatomic, strong) NSMutableArray *hazardsArray;
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#pragma mark - Methods
-(void) retrieveData;
#end
viewController.m
#import "ViewController.h"
#import "Hazards.h"
#interface ViewController ()
#end
// Railway Street Ballymena Coordinates
#define BALLYMENA_LATITUDE 54.857719;
#define BALLYMENA_LONGITUDE -6.280654;
// Span
#define THE_SPAN 0.01f;
#define getDataURL #"localhost:8888/rmb/json.php"
#implementation ViewController
#synthesize json, hazardsArray, mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Create the region
MKCoordinateRegion myRegion;
// Center
CLLocationCoordinate2D center;
center.latitude = BALLYMENA_LATITUDE;
center.longitude = BALLYMENA_LONGITUDE;
//Span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
myRegion.center = center;
myRegion.span = span;
// Set our mapview
[mapView setRegion:myRegion animated: YES];
// Annotation
NSMutableArray *locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Hazards *myAnn;
// Pin to show Royal Mail Ballymena delivery office
myAnn = [[Hazards alloc] init];
location.latitude = BALLYMENA_LATITUDE;
location.longitude = BALLYMENA_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = #"Royal Mail Ballymena";
myAnn.subtitle = #"111, Railway Street";
[locations addObject:myAnn];
[self.mapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Methods
-(void) retrieveData {
NSURL *url = [NSURL URLWithString:getDataURL];
NSData *data = [NSData dataWithContentsOfURL:url];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Setup our hazards array
hazardsArray = [[NSMutableArray alloc] init];
for (int i =0; i < json.count; i++) {
// Create hazard object
NSString *hazardsID = [[json objectAtIndex:i] objectForKey:#"ID"];
NSString *hazardsROUTE = [[json objectAtIndex:i] objectForKey:#"ROUTE"];
NSString *hazardsADDRESS = [[json objectAtIndex:i] objectForKey:#"ADDRESS"];
NSString *hazardsLATITUDE = [[json objectAtIndex:i] objectForKey:#"LATITUDE"];
NSString *hazardsLONGITUDE = [[json objectAtIndex:i] objectForKey:#"LONGITUDE"];
NSString *hazardsHAZARD = [[json objectAtIndex:i] objectForKey:#"HAZARD"];
NSString *hazardsRISK = [[json objectAtIndex:i] objectForKey:#"RISK"];
Hazards *myHazards = [[Hazards alloc] initWithID:hazardsID andROUTE:hazardsROUTE andADDRESS:hazardsADDRESS andLATITUDE:hazardsLATITUDE andLONGITUDE:hazardsLONGITUDE andHAZARD:hazardsHAZARD andRISK:hazardsRISK];
// Add our hazards object to our hazards array
[hazardsArray addObject:myHazards];
}
// [self.mapView addAnnotation:hazardsArray];
}
#end
Many Thanks in Advance
Assuming your retrieveData correctly builds Hazard objects and is called at the right time you could either add them one at a time with this line inside the loop
[self.mapView addAnnotation:myHazards];
or all at once after the loop is finished
[self.mapView addAnnotations:hazardsArray];
I'm trying to extend MKPointAnnotation and add a property to for an NSString called dealLink.
I thought I set it up correctly, but I'm getting this error at the moment:
Property 'dealLink' not found on object of type 'MKPointAnnotation *'
Here's my code in a view controller called MapOffersViewController.m:
#pragma mark - Populate Map
- (void)populateMap:(MKMapView*)map withDeals:(NSArray*) deals
{
NSLog(#"Deals " );
for (NSDictionary *currentDeal in deals) {
CLLocationCoordinate2D ctrpoint;
ctrpoint.latitude = [[[currentDeal objectForKey:#"coords"] objectForKey:#"lat"] doubleValue];
ctrpoint.longitude =[[[currentDeal objectForKey:#"coords"] objectForKey:#"lng"] doubleValue];
MKPointAnnotation *dealAnnotation = [[MKPointAnnotation alloc] init];
dealAnnotation.coordinate = ctrpoint;
dealAnnotation.title = [currentDeal objectForKey:#"vendor"];
**dealAnnotation.dealLink = [currentDeal objectForKey:#"link"];**
NSDictionary *currDict = #{
#"EUR": #"€",
#"GBP": #"₤",
#"USD": #"$",
#"BRL": #"R$"
};
NSString *currName = [currentDeal objectForKey:#"currency"];
NSString *currency = [currDict objectForKey:currName];
dealAnnotation.subtitle = [NSString stringWithFormat:#"%#%i",currency,[[currentDeal objectForKey:#"price"] integerValue ]];
NSLog(#"current deal id is %#",[currentDeal objectForKey:#"id"]);
[map setDelegate:self];
[map addAnnotation:dealAnnotation];
}
}
I'm importing this class called MapAnnotation.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapAnnotation : MKPointAnnotation
{
NSString *title;
NSString *subtitle;
NSString *dealLink;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, retain) NSString *dealLink;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl subTitle:(NSString *)subttl dealLink:(NSString *)dealLnk andCoordinate:(CLLocationCoordinate2D)c2d;
#end
and it's .m:
#import "MapAnnotation.h"
#implementation MapAnnotation
#synthesize title,subtitle,dealLink,coordinate;
- (id)initWithTitle:(NSString *)ttl subTitle:(NSString *)subttl dealLink:(NSString *)dealLnk andCoordinate:(CLLocationCoordinate2D)c2d {
title = ttl;
subtitle = subttl;
dealLink = dealLnk;
coordinate = c2d;
return self;
}
#end
thanks for any help
I used Craig's answer below and this additional code to get this working:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
NSLog(#"callout tapped from del method %#", dealUrl);
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:dealUrl]];
}
- (void)mapView:(MKMapView *)mapView1 didSelectAnnotationView:(MKAnnotationView *)mapView2
{
MapAnnotation *annotation = mapView2.annotation;
NSString *temp = annotation.dealLink;
dealUrl = temp;
// NSLog(#"temp is %#", temp);
}
You're creating an MKPointAnnotation and trying to access dealLink, which is only on MapAnnotations. You need to create a MapAnnotation
....
ctrpoint.longitude =[[[currentDeal objectForKey:#"coords"] objectForKey:#"lng"] doubleValue];
MapAnnotation *dealAnnotation = [[MapAnnotation alloc] init];
dealAnnotation.coordinate = ctrpoint;
....
This is the way where I am taking the current location
NSString* lat = [[NSString alloc]initWithFormat:#"%f",locationManager.location.coordinate.latitude];
NSString* lon = [[NSString alloc]initWithFormat:#"%f",locationManager.location.coordinate.longitude];
NSString *URL = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#,%#&output=csv&sensor=false",lat,lon];
NSURLRequest *rq = [NSURLRequest requestWithURL:[NSURL URLWithString:URL]];
con = [[NSURLConnection alloc] initWithRequest:rq delegate:self];
webData = [[NSMutableData data] retain];
and in the connection delegate method I am getting the current location name.200,9,"IITI Computer Education, Wadala, Mumbai, Maharashtra 400067, India" in the simulator.
Now my question is How can we set annotation on the same place in the map using the string place name which I got previously.
Thanks in advance
First make an objective c class make your .h file look like following
#import <Foundation/Foundation.h>
#import <Mapkit/MKAnnotation.h>
#interface annotation : NSObject <MKAnnotation>
{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property(nonatomic, assign) CLLocationCoordinate2D coordinate;
#property(nonatomic, copy) NSString *title;
#property(nonatomic, copy) NSString *subtitle;
#end
Now in .m file
#import "annotation.h"
#implementation annotation
#synthesize coordinate,title,subtitle;
#end
Now in your controller.m file where you want to add an annotaion make an import of above file
#import "annotation.h"
now you can use the following function to add anotation to any cordinate
-(void)addAnnotations{
annotation *userPositionAnnote = [[annotation alloc]init];
userPositionAnnote.title = #"My Current Position";
userPositionAnnote.coordinate = SetYourCordinates; // set your cordinates here where you want to add annotaion
[YourMap addAnnotation:userPositionAnnote];
MKCoordinateRegion region = {{0.0,0.0}, {0.0,0.0}};
region.center = userPositionAnnote.coordinate;
region.span.longitudeDelta = 0.001;
region.span.latitudeDelta = 0.001;
[YourMap setRegion:region animated:YES];
}
hope this will help you
I keep getting this semantic issue with this code ('MyAnnotation' may not respond to 'initWithDictionary:'), im adding annotations to a map using a plist.
Even though it displays the pin and everything i want it to, i get an semantic issue and cant seem to solve the problem
if anyone could help that would be great thanks
heres the code, the problem is in the //BrewMapViewController.m the error is on this line
MyAnnotation *annotation = [[MyAnnotation alloc] initWithDictionary:breweryDict];
/*MyAnnotation.h*/
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
NSString *test;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, copy) NSString *test;
#end
/*MyAnnotation.m*/
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize coordinate, title, subtitle, test;
- (id) initWithDictionary:(NSDictionary *) dict
{
self = [super init];
if (self != nil) {
coordinate.latitude = [[dict objectForKey:#"latitude"] doubleValue];
coordinate.longitude = [[dict objectForKey:#"longitude"] doubleValue];
self.title = [dict objectForKey:#"name"];
self.subtitle = [dict objectForKey:#"address"];
self.test = [dict objectForKey:#"test"];
}
return self;
}
#end
/*BrewMapViewController.h*/
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface BrewMapViewController : UIViewController <MKMapViewDelegate> {
IBOutlet MKMapView *map;
NSArray *breweries;
}
#end
/*BrewMapViewController.m*/
#import "BrewMapViewController.h"
#import "MyAnnotation.h"
#implementation BrewMapViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
breweries = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"test"
ofType:#"xml"]];
double minLat = [[breweries valueForKeyPath:#"#min.latitude"] doubleValue];
double maxLat = [[breweries valueForKeyPath:#"#max.latitude"] doubleValue];
double minLon = [[breweries valueForKeyPath:#"#min.longitude"] doubleValue];
double maxLon = [[breweries valueForKeyPath:#"#max.longitude"] doubleValue];
MKCoordinateRegion region;
region.center.latitude = (maxLat + minLat) / 2.0;
region.center.longitude = (maxLon + minLon) / 2.0;
region.span.latitudeDelta = (maxLat - minLat) * 1.05;
region.span.longitudeDelta = (maxLon - minLon) * 1.05;
map.region = region;
for (NSDictionary *breweryDict in breweries){
MyAnnotation *annotation = [[MyAnnotation alloc] initWithDictionary:breweryDict];
[map addAnnotation:annotation];
[annotation release];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if (map.userLocation == annotation){
return nil;
}
NSString *identifier = #"MY_IDENTIFIER";
MKAnnotationView *annotationView = [map dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil){
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:identifier]
autorelease];
annotationView.image = [UIImage imageNamed:#"beer.png"];
annotationView.canShowCallout = YES;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.leftCalloutAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"pretzel.png"]] autorelease];
}
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"I've been tapped");
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)dealloc {
[breweries release];
[map release];
[super dealloc];
}
#end
You have to put the method signature for - (id) initWithDictionary:(NSDictionary *) dict into your header file in order to tell BrewMapViewController that the method exists:
/*MyAnnotation.h*/
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
NSString *test;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, copy) NSString *test;
- (id) initWithDictionary:(NSDictionary *) dict;
#end
At the moment I have 1 pin, when you tap the pin it displays information. However I want more than 1 pin at different locations. How would I do this?
This is my code.
Map.m
- (void)viewDidLoad
{
[super viewDidLoad];
[mapview setMapType:MKMapTypeStandard];
[mapview setZoomEnabled:YES];
[mapview setScrollEnabled:YES];
MKCoordinateRegion region = { {0.0, 0.0 }, {0.0, 0.0 } };
region.center.latitude = 52.509078;
region.center.longitude = -1.884799;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[mapview setRegion:region animated:YES];
NewClass *ann = [[NewClass alloc] init];
ann.title = #"AVFC";
ann.subtitle = #"Aston Villa Football Club";
ann.coordinate = region.center;
[mapview addAnnotation:ann];
// Do any additional setup after loading the view, typically from a nib.
}
NewClass.h
#interface NewClass : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
NSString *titleOne;
NSString *subtitleTwo;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#property (nonatomic, copy) NSString *titleOne;
#property (nonatomic, copy) NSString *subtitleTwo;
#end
Create your annotations (however many you want) then add them to an NSArray. You can add them to your MKMapView using [mapview addAnnotations:annotationArray];
MKMapView Ref