usually this code has worked perfectly for me, up until recently I went to update my project to support the latest iOS and when clicking on the map button, receive the error;
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
Prior to using Xcode 9 it would work correctly, so I am guessing the way the code works is slightly different now.
The array is NSArray *arr_OfCountryCode;
And we initialise it in the viewDidLoad
//Initialize NSArray object with Images
arr_OfCountryCode=#[#"AF",#"AL",#"DZ",#"AS",#"AD",#"AO",#"AI",#"AQ",#"AG",#"AR",#"AM",#"AW",#"AC",#"AU",#"AT",#"AZ",#"BS",#"BH",#"BD",#"BB",#"BY",#"BE",#"BZ",#"BJ",#"BM",#"BT",#"BO",#"BA",#"BW",#"BV",#"BR",#"IO",#"VG",#"BN",#"BG",#"BF",#"BI",#"KH",#"CM",#"CA",#"IC",#",CV",#"BQ",#"KY",#"CF",#"EA",#"TD",#"CL",#"CN",#"CX",#"CP",#"CC",#"CO",#"KM",#"CD",#"CG",#"CK",#"CR",#"HR",#"CU",#"CW",#"CY",#"CZ",#"CI",#"DK",#"DG",#"DJ",#"DM",#"DO",#"EC",#"EG",#"SV",#"GQ",#"ER",#"EE",#"ET",#"FK",#"FO",#"FJ",#"FI",#"FR",#"FG",#"PF",#"TF",#"GA",#"GM",#"GE",#"DE",#"GH",#"GI",#"GR",#"GL",#"GD",#"GP",#"GU",#"GT",#"GG",#"GN",#"GW",#"GY",#"HT",#"HM",#"HN",#"HK",#"HU",#"IS",#"IN",#"ID",#"IR",#"IQ",#"IE",#"IM",#"IL",#"IT",#"JM",#"JP",#"JE",#"JO",#"KZ",#"KE",#"KI",#"XK",#"KW",#"KG",#"LA",#"LV",#"LB",#"LS",#"LR",#"LY",#"LI",#"LT",#"LU",#"MO",#"MK",#"MG",#"MW",#"MY",#"MV",#"ML",#"MT",#"MH",#"MQ",#"MR",#"MU",#"YT",#"MX",#"FM",#"MD",#"MC",#"MN",#"ME",#"MS",#"MA",#"MZ",#"MM",#"NA",#"NR",#"NP",#"NL",#"NC",#"NZ",#"NI",#"NE",#"NG",#"NU",#"NF",#"KP",#"MP",#"NO",#"OM",#"PK",#"PW",#"PS",#"PA",#"PG",#"PY",#"PE",#"PH",#"PN",#"PL",#"PT",#"PR",#"QA",#"RO",#"RU",#"RW",#"RE",#"WS",#"SM",#"SA",#"SN",#"RS",#"SC",#"SL",#"SG",#"SX",#"SK",#"SI",#"SB",#"SO",#"ZA",#"GS",#"KR",#"SS",#"ES",#"LK",#"BL",#"SH",#"KN",#"LC",#"MF",#"PM",#"VC",#"SD",#"SR",#"SJ",#"SZ",#"SE",#"CH",#"SY",#"ST",#"TW",#"TJ",#"TZ",#"TH",#"TL",#"TG",#"TK",#"TO",#"TT",#"TA",#"TN",#"TR",#"TM",#"TC",#"TV",#"UM",#"VI",#"UG",#"UA",#"AE",#"GB",#"US",#"UY",#"UZ",#"VU",#"VA",#"VE",#"VN",#"WF",#"EH",#"YE",#"ZM",#"ZW",#"AX"];
When the user taps the button, a location on the map is shown at random, within the actionMethod to do that is;
str_Type = #"Randum";
self.mapView.hidden = NO;
int randomIndex = arc4random() % [arr_OfCountryCode count];
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=false",[arr_OfCountryCode objectAtIndex:randomIndex]];
NSURL *url = [[NSURL alloc] initWithString:urlString];
I am struggling as to why the array is classed as empty when it worked for multiple iOS versions and devices prior to the latest.
It is showing as nil as soon as I check it in Xcode, other arrays initialise before it with no issue, I even tried copying an existing array, renaming it to *arr_OfCountryCode; and that still showed as nil !
In this method (entire posted below) I believe the problem is occuring.
- (IBAction)actionMethod:(UIButton *)sender {
if ([sender tag] == 0) {
self.musicView.hidden = NO;
[self.tbl_MusicTable reloadData];
} else if ([sender tag] == 1) {
str_Type = #"Randum";
self.mapView.hidden = NO;
int randomIndex = arc4random() % [arr_OfCountryCode count];
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=false",[arr_OfCountryCode objectAtIndex:randomIndex]];
NSURL *url = [[NSURL alloc] initWithString:urlString];
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:url] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"%#",error.description);
} else {
NSDictionary *jsonObject=[NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableLeaves
error:nil];
NSDictionary *places = [[[[jsonObject objectForKey:#"results"] objectAtIndex:0] objectForKey:#"geometry"] objectForKey:#"location"];
NSDictionary *locations = [[[jsonObject objectForKey:#"results"] objectAtIndex:0] objectForKey:#"address_components"];
float lat = [[places objectForKey:#"lat"] floatValue];
float lon = [[places objectForKey:#"lng"] floatValue];
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.50;
span.longitudeDelta = 0.50;
location.latitude = lat;
location.longitude = lon;
region.span = span;
region.center = location;
[self.mk_MapView setRegion:region animated:YES];
NSString *str_Title = [[locations valueForKey:#"long_name"] objectAtIndex:0];
NSString *str_Short = [[locations valueForKey:#"short_name"] objectAtIndex:0];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = location;
point.title = str_Title;
point.subtitle = str_Short;
[self.mk_MapView addAnnotation:point];
}
}];
}
}
The further code for corelocation is here
#pragma mark - CLLocationManager Delegate Method
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
if ([str_Type isEqualToString:#"Custom"]) {
CLLocation *currentLocation = newLocation;
NSString *str_Longitude;
NSString *str_Latitude;
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.020;
span.longitudeDelta = 0.020;
location.latitude = currentLocation.coordinate.latitude;
location.longitude = currentLocation.coordinate.longitude;
region.span = span;
region.center = location;
[self.mk_MapView setRegion:region animated:YES];
if (currentLocation != nil) {
str_Longitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
str_Latitude = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
// Reverse Geocoding
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = currentLocation.coordinate;
point.title = placemark.country;
point.subtitle = placemark.locality;
[self.mk_MapView addAnnotation:point];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
} else {
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = location;
point.title = placemark.country;
point.subtitle = placemark.locality;
[self.mk_MapView addAnnotation:point];
}
}
#pragma mark - MKMapView Delegate Methods
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != self.mk_MapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[self.mk_MapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
//pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
//pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:#"HesOnThisMap"]; //
}
else {
//[self.mk_MapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
MKAnnotationView *aV;
for (aV in views) {
CGRect endFrame = aV.frame;
aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - 230.0, aV.frame.size.width, aV.frame.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.45];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[aV setFrame:endFrame];
[UIView commitAnimations];
}
}
It was to do with the google maps api callbacks, it was crashing when it hit the maximum callbacks
I am using WMSOnGooglemaps sdk for base maps . I can see my layers from geoserver overlayed on google maps but I am stuck at getfeatureinfo request(I want information of layer on click of layer).I am geeting the info on click of layer but it is wrong.
//Code to display layer
- (void)loadView
{
GMSTileURLConstructor urls1 = ^(NSUInteger x, NSUInteger y, NSUInteger z)
{
bbox = bboxFromXYZ(x,y,z);
NSString *urlKN1 = [NSString stringWithFormat:#"http://IPADDRESS/geoserver/wms?service=WMS&version=1.1.1&request=GetMap&layers=gidc:plots_category_wise&bbox=%f,%f,%f,%f&width=768&height=1024&srs=EPSG:900913&format=image/png&transparent=true",
bbox.left, bbox.bottom,bbox.right,bbox.top];
return [NSURL URLWithString:urlKN1];
};
GMSTileLayer *tileLayer1 = [GMSURLTileLayer tileLayerWithURLConstructor:urls1];
tileLayer1.map = mapView;
}
- (void)mapView:(GMSMapView *)mapView1 didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
{
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(coordinate.latitude,coordinate.longitude);
NSLog(#"Latitude= %f lonitude = %f",coordinate.latitude,coordinate.longitude);
GMSMarker *marker = [GMSMarker markerWithPosition:position];
point = [mapView1.projection pointForCoordinate:marker.position];
//ankita.dutta#hardcastlegis.com
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc]initWithCoordinate:coordinate coordinate:coordinate];
NSLog(#"Bounds.minx = %f,%f,%f,%f",bounds.southWest.longitude,bounds.northEast.latitude,bounds.northEast.longitude,bounds.southWest.latitude);
NSLog(#"Pointer: %d, %d",[[NSNumber numberWithFloat:point.x] intValue],[[NSNumber numberWithFloat:point.y] intValue] );
GMSVisibleRegion region;
region = mapView.projection.visibleRegion;
GMSCoordinateBounds *bounds1 = [[GMSCoordinateBounds alloc] initWithRegion:region];
NSLog(#"Bounds.minx = %.15f,%.15f,%.15f,%.15f",bounds1.southWest.longitude,bounds1.northEast.latitude,bounds1.northEast.longitude,bounds1.southWest.latitude);
[self getInfo:[[NSNumber numberWithFloat:point.x] intValue] :[[NSNumber numberWithFloat:point.y] intValue] :bounds1.southWest.longitude :bounds1.northEast.latitude :bounds1.northEast.longitude :bounds1.southWest.latitude];
}
-(void)getInfo : (int) xValue : (int) yValue :(double)bboxLMin :(double)bboxLMax :(double)bboxRMin :(double)bboxTMax
{
// [self showLoadingView:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
NSMutableURLRequest * request=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://117.239.80.70:8282/geoserver/wms?service=WMS&version=1.1.1&srs=EPSG:4326&bbox=%.15f,%.15f,%.15f,%.15f&styles=&&buffer=40&info_format=application/json&request=GetFeatureInfo&layers=gidc:plots_category_wise&query_layers=gidc:plots_category_wise&width=%d&height=%d&x=%d&y=%d",bboxLMin,bboxLMax,bboxRMin,bboxTMax, [[NSNumber numberWithFloat:mapView.frame.size.width] intValue],[[NSNumber numberWithFloat:mapView.frame.size.height] intValue],xValue,yValue]]];
NSURLSession * session =[NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error)
{
if (data!=NULL)
{
dispatch_async(dispatch_get_main_queue(), ^
{
//[self showLoadingView:NO];
NSMutableDictionary *listDict=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"Responce =%#",listDict);
NSMutableArray *dataArr = [[listDict valueForKey:#"features"]valueForKey:#"properties"];
[self response:dataArr];
});
}
}]resume];
});
}
I want to show two location's distance in mapkit, I have tried my process its not showing the distance between the location. tried below codes its not working, can any one help me in coding.
MKMapView * mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 294, 320, 122)];
mapView.showsUserLocation = YES;
mapView.delegate = self;
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
MKPlacemark *placemark1 = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(9.9176458, 78.1228237) addressDictionary:nil];
[request setSource:[[MKMapItem alloc] initWithPlacemark:placemark1]];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(13.0475604, 80.2089535) addressDictionary:nil];
request.destination = [[MKMapItem alloc] initWithPlacemark:placemark];
// [request setDestination:myMapItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile]; // This can be limited to automobile and walking directions.
[request setRequestsAlternateRoutes:YES]; // Gives you several route options.
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (!error) {
for (MKRoute *route in [response routes]) {
[mapView addOverlay:[route polyline] level:MKOverlayLevelAboveRoads]; // Draws the route above roads, but below labels.
// You can also get turn-by-turn steps, distance, advisory notices, ETA, etc by accessing various route properties.
}
}
}];
[self.view addSubview:mapView];
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
MKPolylineRenderer *renderer =
[[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.strokeColor = [UIColor blueColor];
renderer.lineWidth = 5.0;
return renderer;
}
Please any help me .
If you check error in the -calculateDirectionsWithCompletionHandler:
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (!error) {
for (MKRoute *route in [response routes]) {
[mapView addOverlay:[route polyline] level:MKOverlayLevelAboveRoads]; // Draws the route above roads, but below labels.
// You can also get turn-by-turn steps, distance, advisory notices, ETA, etc by accessing various route properties.
}
}
else {
NSLog(#"%#", error);
}
}];
You will probably see
Error Domain=MKErrorDomain Code=5 "Directions Not Available" UserInfo=0x7fefe3bb5660 {NSLocalizedFailureReason=A route to the nearest road cannot be determined., MKErrorGEOError=-403, MKDirectionsErrorCode=6, NSLocalizedDescription=Directions Not Available}
Which means that it is not possible to calculate directions from given location.
Here is my code; I use CLLocationManager Delegate to compute distance between two location and MKMapView Delegate. here is my code, it may help you.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)location{
float distance = 0.0f;
NSMutableArray *locationArray = [[NSMutableArray alloc] init];
for (CLLocation *newLocation in location) {
[locationArray addObject:newLocation];
}
for (int i = 0 ; i < locationArray.count; i++) {
CLLocation *newLocation = [locationArray objectAtIndex:i];
distance += [newLocation distanceFromLocation:[locationArray objectAtIndex:i+1]];
}
NSLog(#"%f",distance);
CLLocationCoordinate2D cordinates [locationsArray.count];
MKPolyline *userLocationsPolyLine = [MKPolyline polylineWithCoordinates:cordinates count:locationsArray.count];
[userMapView setDelegate:self];
[userMapView addOverlay:userLocationsPolyLine];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
if ([overlay isKindOfClass:[MKPolyline class]]){
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
renderer.lineWidth = 3;
return renderer;
}
return nil;
}