Creating an array of CLLocationCoordinates - ios

I'm attempting to get an array of latitude and longitude double values which I have stored in parse.com. I want to be able to convert these back into CLLocationCoordinates which I can then use to create MKPloylines in a custom table view.
However I'm not too sure how I can store an array of CLLocationCoordinates.
Here is my code:
_latitudeArray = [object objectForKey:#"latitude"];
[_parseLatitudeArray addObject:_latitudeArray];
_longitudeArray = [object objectForKey:#"longitude"];
[_parseLongitudeArray addObject:_longitudeArray];
for (int i=0; i < [_parseLatitudeArray count]; i++) {
_latitude = [self.parseLatitudeArray objectAtIndex:i];
_longitude = [self.parseLongitudeArray objectAtIndex:i];
CLLocationCoordinate2D coordinates [[_latitude count]];
for (int i = 0; i < [_latitude count]; i++) {
CLLocationCoordinate2D coordinate;
double latitude = [[_latitude objectAtIndex:i] doubleValue];
double longitude = [[_longitude objectAtIndex:i] doubleValue];
coordinate.latitude = latitude;
coordinate.longitude = longitude;
coordinates[i] = coordinate;
}
[_coordinatesArray addObject:coordinates];
}
NSLog(#"coordinates array = %#", _coordinatesArray);
At first I figured I would be able to do it using [_coordinatesArray addObject:coordinates]; but then realised that would not work!
I may be missing something really basic but any help would be appreciated.
Thanks
EDIT:
property Definitions:
#property NSMutableArray *latitudeArray;
#property NSMutableArray *parseLatitudeArray;
#property NSMutableArray *longitudeArray;
#property NSMutableArray *parseLongitudeArray;
#property NSMutableArray *coordinatesArray;
#property NSArray *latitude;
#property NSArray *longitude;
#property CLLocationCoordinate2D *coordinates;

Instead of creating a C-array of structs, wrap each struct into an object and add it to an NSMutableArray. So after you create coordinate, just:
[coordinatesArray addObject: [NSValue valueWithMKCoordinate:coordinate]];
And to get the value back out:
CLLocationCoordinate2D coordinate;
[coordinatesArray[i] getValue:&coordinate];
So, assuming that self.latitude and self.longitude are NSArrays of NSStrings:
//only property is now
#property (nonatomic, strong) NSArray * locations
-(void) loadCoordinatesFromParse {
NSDictionary * parseData;
//load parseData from Parse here
NSMutableArray * coordinates = [NSMutableArray array];
NSArray * latitudes = [parseData objectForKey:#"latitude"];
NSArray *longitudes = [parseData objectForKey:#"longitude"];
for (int i = 0; i < [latitudes count]; i++) {
double latitude = [latitudes[i] doubleValue];
double longitude = [longitudes[i] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
[coordinates addObject: [NSValue valueWithMKCoordinate:coordinate]];
}
NSLog(#"coordinates array = %#", coordinates);
self.locations = [NSArray arrayWithArray: coordinates];
}

Related

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

Only showing one pin on the map from my array

I am having trouble showing pins on a map loading coordinates, title and subtitle from parse.com.
Here is my code. Is there any logical wrong? I get only the third row in the db showing, instead of all five that I have at the parse.com.
for(int i = 0; i<objects.count; i++)
{
int raknare = 1;
raknare++;
PFObject *tempObject = [kundUppgifter objectAtIndex:raknare];
PFGeoPoint *geoPoint = [tempObject objectForKey:#"CLAT"];
PFGeoPoint *geoPoint2 = (PFGeoPoint *)geoPoint;
NSString *cname = #"CNAME";
NSString *ctown = #"CTOWN";
kundUppgifter = [[NSArray alloc] initWithArray:objects];
objects = [NSArray arrayWithObjects:cname,ctown,geoPoint,nil];
NSMutableArray * locations = [[NSMutableArray alloc]init];
Annotation * myAnn;
myAnn = [[Annotation alloc]init];
CLLocationCoordinate2D location;
double longitude;
double latitude;
latitude = geoPoint2.latitude;
longitude = geoPoint2.longitude;
location.latitude = latitude;
location.longitude = longitude;
geoPoint.latitude = latitude;
geoPoint.longitude = longitude;
myAnn.coordinate = location;
myAnn.title = [tempObject objectForKey:#"CNAME"];
myAnn.subtitle = [tempObject objectForKey:#"CTOWN"];
[locations addObject:myAnn];
[self.myMapView addAnnotations:locations];
NSLog(#"geopoint is a pfobject with latitude %f, and longitude %f kundnamn %#,stad %#,", latitude, longitude, cname, ctown);
NSLog(#"%#", cname);
NSLog(#"%#", objects);
}
}
}];
Happy if you can help!
for(int i = 0; i<objects.count; i++)
{
int raknare = 1;
raknare++;
PFObject *tempObject = [kundUppgifter objectAtIndex:raknare];
}
This code inside of your loop will make raknare == 2 every iteration of the loop. You want to use the i variable you set to pull from -objectAtIndex: like this
for(int i = 0; i<objects.count; i++)
{
// This gives you a different object each iteration of the loop
PFObject *tempObject = [kundUppgifter objectAtIndex:i];
}

property identifier not found on CLRegion

I am having an array of CLregions and this is my code:
NSArray *_regionArray;
NSArray *_geofences_regions;
... in the ViewDidLoad
_geofences_regions = [self buildGeofenceData];
....
- (NSArray*) buildGeofenceData {
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"regions" ofType:#"plist"];
_regionArray = [NSArray arrayWithContentsOfFile:plistPath];
NSMutableArray *geofences = [NSMutableArray array];
for(NSDictionary *regionDict in _regionArray) {
CLRegion *region = [self mapDictionaryToRegion:regionDict];
[geofences addObject:region];
}
return [NSArray arrayWithArray:geofences];
}
- (CLRegion*)mapDictionaryToRegion:(NSDictionary*)dictionary {
NSString *title = [dictionary valueForKey:#"title"];
CLLocationDegrees latitude = [[dictionary valueForKey:#"latitude"] doubleValue];
CLLocationDegrees longitude =[[dictionary valueForKey:#"longitude"] doubleValue];
CLLocationCoordinate2D centerCoordinate = CLLocationCoordinate2DMake(latitude, longitude);
CLLocationDistance regionRadius = [[dictionary valueForKey:#"radius"] doubleValue];
return [[CLRegion alloc] initCircularRegionWithCenter:centerCoordinate
radius:regionRadius
identifier:title];
}
In the following code, the property identifier is not found on object of type id.
Why is that? Shouldn't _geofences_regios[i] return a CLRegion?
/*check for region*/
CLLocationCoordinate2D coordinate = [bestLocation coordinate];
for (int i=0; i<[_geofences_regions count]; i++) {
if ([_geofences_regions[i] containsCoordinate:coordinate]) {
[self.delegate locationManager:self regionEntered:_geofences_regions[i].identifier ];
}
}
/end checking for region/
Please answer on the above question, do not suggest me of using other delegate methods like didEnterRegion.
Thanks!
That's because the object returned by the array, by default is of type id that doesn´t have an identifier attribute, you can do a cast to avoid the error:
[self.delegate locationManager:self regionEntered:((CLRegion*)_geofences_regions[i]).identifier ];

How to loop through arrays

Now I loop through one Array at once and calculate distance like this:
- (void)calculateDistance
{
ann = [dict objectForKey:#"Blue"];
for(int i = 0; i < [ann count]; i++) {
NSString *coordinates = [[ann objectAtIndex:i] objectForKey:#"Coordinates"];
double realLatitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:1] doubleValue];
double realLongitude = [[[coordinates componentsSeparatedByString:#","] objectAtIndex:0] doubleValue];
// Calculating distance
CLLocation *pinLocation = [[CLLocation alloc]
initWithLatitude:realLatitude
longitude:realLongitude];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:mapView.userLocation.coordinate.latitude
longitude:mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
// Adding distance to dictionaries
if (distance > 1000) {
NSString *dist = [NSString stringWithFormat:#"%.2f km.", distance/1000];
NSMutableDictionary *inDict = [[NSMutableDictionary alloc] init];
inDict = [ann objectAtIndex:i];
[inDict setValue:dist forKey:#"Distance"];
}
else{
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
NSMutableDictionary *inDict = [[NSMutableDictionary alloc] init];
inDict = [ann objectAtIndex:i];
[inDict setValue:dist forKey:#"Distance"];
}
}
}
My data structure is:
How to loop through all Array's at once? I have Array which contains all my Array's named "resultArray", but this code doesn't work:
ann = [dict objectForKey:resultArray];
NSLog(#"%#", resultArray);
2013-05-05 10:57:03.643 testApp[5708:907] (
Black,
Green,
Orange,
Blue,
Darkblue
)
I guess you want to enumerate through the keys stored in resultArray and calculate the distance and add that calculated values to it.
- (void)calculateDistance
{
//Enumerates through resultArray
for (NSString *key in resultArray) {
//ann array is considered as an instance of NSMutableArray
ann = dict[key];
for(int i = 0; i < [ann count]; i++) {
NSMutableDictionary *inDict = [ann[i] mutableCopy];
NSString *coordinates = inDict[#"Coordinates"];
NSArray *coordinateComponents = [coordinates componentsSeparatedByString:#","];
double realLatitude = [coordinateComponents[1] doubleValue];
double realLongitude = [coordinateComponents[0] doubleValue];
// Calculating distance
CLLocation *pinLocation = [[CLLocation alloc] initWithLatitude:realLatitude
longitude:realLongitude];
CLLocation *userLocation = [[CLLocation alloc]
initWithLatitude:mapView.userLocation.coordinate.latitude
longitude:mapView.userLocation.coordinate.longitude];
CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
// Adding distance to dictionaries
if (distance > 1000) {
NSString *dist = [NSString stringWithFormat:#"%.2f km.", distance/1000];
[inDict setValue:dist forKey:#"Distance"];
}
else{
NSString *dist = [NSString stringWithFormat:#"%4.0f m.", distance];
[inDict setValue:dist forKey:#"Distance"];
}
//Inserting the modified values to the main array
[ann replaceObjectAtIndex:i withObject:inDict];
}
}
}
ann = [dict objectForKey:resultArray];
for(NSArray *colourArray in ann)
{
for(NSDictionary *itemDictionary in colourArray)
{
NSLog(#"Coordinates = %#",[itemDictionary objectForKey:#"Coordinates"]);
NSLog(#"Name = %#",[itemDictionary objectForKey:#"Name"]);
NSLog(#"Address = %#",[itemDictionary objectForKey:#"Address"]);
}
}
Hope it will help you .

NSNumber conversion-pair latitude and longitude

NSNumber *a;
for(NSDictionary *item in[res valueForKey:#"snapshot"])
{
a=[item valueForKey:#"lat"];
NSLog(#"%#",a);
b=[item valueForKey:#"lng"];
NSLog(#"%#",b);
}
that writes on console :
("29.13","29.38","29.31","29.30","29.43" )
("94.13","94.38","93.30","94.58","94.34" )`
How could I get each values to convert double? I want to get each latitude and longitude pairs out of this output.
According to your NSLog, the values you get from valueForKey: are NSArrays, not NSNumber. So simply go thru those arrays.
for(NSDictionary *item in[res valueForKey:#"snapshot"])
{
NSArray* latitudesList = [item valueForKey:#"lat"];
NSArray* longitudesList = [item valueForKey:#"lng"];
NSInteger idx = 0;
NSInteger nb = MIN( latitudesList.count , longitudesList.count );
for(NSInteger idx = 0; idx < nb; ++idx)
{
double lat = [[latitudesList objectAtIndex:idx] doubleValue];
double lng = [[longitudesList objectAtIndex:idx] doubleValue];
NSLog(#"Pair #%d = { %f , %f }", idx, lat, lng);
}
}

Resources